diff --git a/hooks/hook_adminmenu.php b/hooks/hook_adminmenu.php new file mode 100644 index 0000000000000000000000000000000000000000..edfee988240a4634c1325c7456fc63a684059284 --- /dev/null +++ b/hooks/hook_adminmenu.php @@ -0,0 +1,26 @@ +<?php + +declare(strict_types=1); + +use SimpleSAML\Locale\Translate; +use SimpleSAML\Module\accounting\Helpers\ModuleRoutesHelper; +use SimpleSAML\Module\accounting\ModuleConfiguration; + +function accounting_hook_adminmenu(\SimpleSAML\XHTML\Template &$template): void +{ + $menuKey = 'menu'; + + $moduleRoutesHelper = new ModuleRoutesHelper(); + + $profilePageEntry = [ + ModuleConfiguration::MODULE_NAME => [ + 'url' => $moduleRoutesHelper->getUrl(ModuleRoutesHelper::PATH_USER_PERSONAL_DATA), + 'name' => Translate::noop('Profile Page'), + ], + ]; + + // Use array_splice to put our entry before the "Log out" entry. + array_splice($template->data[$menuKey], -1, 0, $profilePageEntry); + + $template->getLocalization()->addModuleDomain(ModuleConfiguration::MODULE_NAME); +} \ No newline at end of file diff --git a/hooks/hook_configpage.php b/hooks/hook_configpage.php new file mode 100644 index 0000000000000000000000000000000000000000..9b103adc7736fd19a54545dbf798cc335981f97c --- /dev/null +++ b/hooks/hook_configpage.php @@ -0,0 +1,20 @@ +<?php + +declare(strict_types=1); + +use SimpleSAML\Locale\Translate; +use SimpleSAML\Module\accounting\Helpers\ModuleRoutesHelper; +use SimpleSAML\Module\accounting\ModuleConfiguration; +use SimpleSAML\XHTML\Template; + +function accounting_hook_configpage(Template &$template): void +{ + $moduleRoutesHelper = new ModuleRoutesHelper(); + + $template->data['links'][] = [ + 'href' => $moduleRoutesHelper->getUrl(ModuleRoutesHelper::PATH_ADMIN_CONFIGURATION_STATUS), + 'text' => Translate::noop('Profile Page configuration status'), + ]; + + $template->getLocalization()->addModuleDomain(ModuleConfiguration::MODULE_NAME); +} diff --git a/routing/routes/routes.yml b/routing/routes/routes.yml index 6b1972c0ad84a604328e4eb16276f14b0c4a1971..c6bc1a186a23913a851a3aa3e93af975bc7e2ea0 100644 --- a/routing/routes/routes.yml +++ b/routing/routes/routes.yml @@ -3,6 +3,7 @@ accounting-setup: path: /setup defaults: { _controller: 'SimpleSAML\Module\accounting\Http\Controllers\Test::setup' } +# TODO mivanci delete accounting-job-runner: path: /job-runner defaults: { _controller: 'SimpleSAML\Module\accounting\Http\Controllers\Test::jobRunner' } diff --git a/src/Entities/Bases/AbstractProvider.php b/src/Entities/Bases/AbstractProvider.php index f96a449db5548180a278537bc3fbc14532c28222..63b43535bfc0c75de90730f48d0a2597e4de2123 100644 --- a/src/Entities/Bases/AbstractProvider.php +++ b/src/Entities/Bases/AbstractProvider.php @@ -42,6 +42,13 @@ abstract class AbstractProvider return $this->entityId; } + public function getDescription(): ?string + { + // TODO mivanci + return null; + } + + protected function resolveEntityId(): string { if ( diff --git a/src/Entities/ConnectedServiceProvider/Bag.php b/src/Entities/ConnectedServiceProvider/Bag.php index 95b77877c762875f3cb79ccc63eaad02f7d74297..9507d8f45aa072d8c3cce369305fe9e417b7180d 100644 --- a/src/Entities/ConnectedServiceProvider/Bag.php +++ b/src/Entities/ConnectedServiceProvider/Bag.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + namespace SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider; use SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider; diff --git a/src/Helpers/ModuleRoutesHelper.php b/src/Helpers/ModuleRoutesHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..ed41487ec70ff43ab744f97e3df745c25b7253ef --- /dev/null +++ b/src/Helpers/ModuleRoutesHelper.php @@ -0,0 +1,31 @@ +<?php + +namespace SimpleSAML\Module\accounting\Helpers; + +use SimpleSAML\Module\accounting\ModuleConfiguration; +use SimpleSAML\Utils\HTTP; + +class ModuleRoutesHelper +{ + public const PATH_ADMIN_CONFIGURATION_STATUS = 'admin/configuration/status'; + + public const PATH_USER_PERSONAL_DATA = 'user/personal-data'; + + protected HTTP $sspHttpUtils; + + public function __construct(HTTP $sspHttpUtils = null) + { + $this->sspHttpUtils = $sspHttpUtils ?? new HTTP(); + } + + public function getUrl(string $path, array $parameters = []): string + { + $url = $this->sspHttpUtils->getBaseURL() . 'module.php/' . ModuleConfiguration::MODULE_NAME . '/' . $path; + + if (!empty($parameters)) { + $url = $this->sspHttpUtils->addURLParameters($url, $parameters); + } + + return $url; + } +} diff --git a/src/Http/Controllers/Admin/Configuration.php b/src/Http/Controllers/Admin/Configuration.php index 7c71d1b47af571cfa4992dfb2da7c1fdb56fbe35..6c977e30fd87e43831d3396faf9777c7c2d97d4d 100644 --- a/src/Http/Controllers/Admin/Configuration.php +++ b/src/Http/Controllers/Admin/Configuration.php @@ -7,8 +7,11 @@ namespace SimpleSAML\Module\accounting\Http\Controllers\Admin; use Exception; use Psr\Log\LoggerInterface; use SimpleSAML\Configuration as SspConfiguration; +use SimpleSAML\Module\accounting\Helpers\ModuleRoutesHelper; use SimpleSAML\Module\accounting\ModuleConfiguration; +use SimpleSAML\Module\accounting\Services\HelpersManager; use SimpleSAML\Module\accounting\Stores\Builders\JobsStoreBuilder; +use SimpleSAML\Module\accounting\Trackers\Builders\AuthenticationDataTrackerBuilder; use SimpleSAML\Session; use SimpleSAML\Utils; use SimpleSAML\Utils\Auth; @@ -22,16 +25,19 @@ class Configuration protected Session $session; protected LoggerInterface $logger; protected Utils\Auth $sspAuthUtils; + protected HelpersManager $helpersManager; public function __construct( SspConfiguration $sspConfiguration, Session $session, LoggerInterface $logger, + HelpersManager $helpersManager, Utils\Auth $sspAuthUtils = null ) { $this->sspConfiguration = $sspConfiguration; $this->session = $session; $this->logger = $logger; + $this->helpersManager = $helpersManager; $this->sspAuthUtils = $sspAuthUtils ?? new Utils\Auth(); $this->sspAuthUtils->requireAdmin(); @@ -48,17 +54,40 @@ class Configuration $moduleConfiguration = null; $configurationValidationErrors = null; $jobsStore = null; + $defaultDataTrackerAndProvider = null; + $setupNeeded = false; + $runSetup = $request->query->has('runSetup'); try { $moduleConfiguration = new ModuleConfiguration(); + $defaultDataTrackerAndProvider = + (new AuthenticationDataTrackerBuilder($moduleConfiguration, $this->logger)) + ->build($moduleConfiguration->getDefaultDataTrackerAndProviderClass()); + + if ($defaultDataTrackerAndProvider->needsSetup()) { + if ($runSetup) { + $defaultDataTrackerAndProvider->runSetup(); + } else { + $setupNeeded = true; + } + } + if ( $moduleConfiguration->getAccountingProcessingType() === ModuleConfiguration\AccountingProcessingType::VALUE_ASYNCHRONOUS ) { $jobsStore = (new JobsStoreBuilder($moduleConfiguration, $this->logger)) ->build($moduleConfiguration->getJobsStoreClass()); + if ($jobsStore->needsSetup()) { + if ($runSetup) { + $jobsStore->runSetup(); + } else { + $setupNeeded = true; + } + } } + // TODO mivanci setup for additional trackers from configuration } catch (Throwable $exception) { $configurationValidationErrors = $exception->getMessage(); } @@ -67,6 +96,10 @@ class Configuration 'moduleConfiguration' => $moduleConfiguration, 'configurationValidationErrors' => $configurationValidationErrors, 'jobsStore' => $jobsStore, + 'defaultDataTrackerAndProvider' => $defaultDataTrackerAndProvider, + 'setupNeeded' => $setupNeeded, + 'profilePageUri' => $this->helpersManager->getModuleRoutesHelper() + ->getUrl(ModuleRoutesHelper::PATH_USER_PERSONAL_DATA), ]; $template = new Template($this->sspConfiguration, 'accounting:admin/configuration/status.twig'); diff --git a/src/Http/Controllers/Test.php b/src/Http/Controllers/Test.php index 26878a8d441f26a44703165e61ad1f1a83469545..697a50ad3c06ba935a4637c47148fb33f21bd8a3 100644 --- a/src/Http/Controllers/Test.php +++ b/src/Http/Controllers/Test.php @@ -21,7 +21,7 @@ use SimpleSAML\XHTML\Template; use Symfony\Component\HttpFoundation\Request; /** - * TODO mivanci delete this file + * TODO mivanci delete this file before release * @psalm-suppress all */ class Test diff --git a/src/Http/Controllers/User/Profile.php b/src/Http/Controllers/User/Profile.php index dfd427db5834e839692b5b17dd34bef6de43aa85..cbd467238459c4528d5e723ca99c0d5c3daa1b84 100644 --- a/src/Http/Controllers/User/Profile.php +++ b/src/Http/Controllers/User/Profile.php @@ -6,9 +6,12 @@ use Psr\Log\LoggerInterface; use SimpleSAML\Auth\Simple; use SimpleSAML\Configuration as SspConfiguration; use SimpleSAML\HTTP\RunnableResponse; -use SimpleSAML\Module; +use SimpleSAML\Module\accounting\Exceptions\Exception; +use SimpleSAML\Module\accounting\Helpers\AttributesHelper; use SimpleSAML\Module\accounting\ModuleConfiguration; +use SimpleSAML\Module\accounting\ModuleConfiguration\ConnectionType; use SimpleSAML\Module\accounting\Providers\Builders\AuthenticationDataProviderBuilder; +use SimpleSAML\Module\accounting\Providers\Interfaces\AuthenticationDataProviderInterface; use SimpleSAML\Session; use SimpleSAML\XHTML\Template; use Symfony\Component\HttpFoundation\Request; @@ -76,61 +79,71 @@ class Profile $normalizedAttributes[$name] = implode('; ', $value); } - die(var_dump($normalizedAttributes)); - $template = new Template($this->sspConfiguration, 'accounting:user/personal-data.twig'); + $template = $this->resolveTemplate('accounting:user/personal-data.twig'); $template->data = compact('normalizedAttributes'); + return $template; } public function connectedOrganizations(Request $request): Template { - // TODO mivanci make sure to use slave connection for data provider if available - $this->authSimple->requireAuth(); - $attributes = $this->authSimple->getAttributes(); - $idAttributeName = $this->moduleConfiguration->getUserIdAttributeName(); + $userIdentifier = $this->resolveUserIdentifier(); - if (empty($attributes[$idAttributeName]) || !is_array($attributes[$idAttributeName])) { - $message = sprintf('No identifier %s present in user attributes.', $idAttributeName); - throw new Module\accounting\Exceptions\Exception($message); - } + $authenticationDataProvider = $this->resolveAuthenticationDataProvider(); + + $this->removeDebugDisplayLimits(); + $connectedServiceProviderBag = $authenticationDataProvider->getConnectedServiceProviders($userIdentifier); + + $template = $this->resolveTemplate('accounting:user/connected-organizations.twig'); + $template->data = compact('connectedServiceProviderBag'); + + return $template; + } + + public function activity(Request $request): Template + { + $userIdentifier = $this->resolveUserIdentifier(); + + $authenticationDataProvider = $this->resolveAuthenticationDataProvider(); - $userIdentifier = (string)reset($attributes[$idAttributeName]); + $page = ($page = (int)$request->query->get('page', 1)) > 0 ? $page : 1; - $authenticationDataProvider = $this->authenticationDataProviderBuilder - ->build($this->moduleConfiguration->getDefaultDataTrackerAndProviderClass()); + // TODO mivanci make maxResults configurable + $maxResults = 10; + $firstResult = ($page - 1) * $maxResults; $this->removeDebugDisplayLimits(); - var_dump($authenticationDataProvider->getConnectedServiceProviders($userIdentifier)); - die(); - $data = []; - $template = new Template($this->sspConfiguration, 'accounting:user/personal-data.twig'); - $template->data = compact('data'); + $activityBag = $authenticationDataProvider->getActivity($userIdentifier, $maxResults, $firstResult); + + $template = $this->resolveTemplate('accounting:user/activity.twig'); + $template->data = compact('activityBag', 'page', 'maxResults'); + return $template; } - public function activity(): Template + protected function resolveUserIdentifier(): string { - $this->authSimple->requireAuth(); $attributes = $this->authSimple->getAttributes(); $idAttributeName = $this->moduleConfiguration->getUserIdAttributeName(); if (empty($attributes[$idAttributeName]) || !is_array($attributes[$idAttributeName])) { $message = sprintf('No identifier %s present in user attributes.', $idAttributeName); - throw new Module\accounting\Exceptions\Exception($message); + throw new Exception($message); } - $userIdentifier = (string)reset($attributes[$idAttributeName]); - - $authenticationDataProvider = $this->authenticationDataProviderBuilder - ->build($this->moduleConfiguration->getDefaultDataTrackerAndProviderClass()); + return (string)reset($attributes[$idAttributeName]); + } - $this->removeDebugDisplayLimits(); - var_dump($authenticationDataProvider->getActivity($userIdentifier)); - die(); - $data = []; - $template = new Template($this->sspConfiguration, 'accounting:user/personal-data.twig'); - $template->data = compact('data'); - return $template; + /** + * @throws Exception + */ + protected function resolveAuthenticationDataProvider(): AuthenticationDataProviderInterface + { + return $this->authenticationDataProviderBuilder + ->build( + $this->moduleConfiguration->getDefaultDataTrackerAndProviderClass(), + ConnectionType::SLAVE + ); } public function logout(): Response @@ -149,9 +162,9 @@ class Profile */ protected function prepareToNameAttributeMap(): array { - return Module\accounting\Helpers\AttributesHelper::getMergedAttributeMapForFiles( + return AttributesHelper::getMergedAttributeMapForFiles( $this->sspConfiguration->getBaseDir(), - Module\accounting\Helpers\AttributesHelper::MAP_FILES_TO_NAME + AttributesHelper::MAP_FILES_TO_NAME ); } @@ -162,4 +175,14 @@ class Profile ini_set('xdebug.var_display_max_children', -1); ini_set('xdebug.var_display_max_data', -1); } + + protected function resolveTemplate(string $template): Template + { + $templateInstance = new Template($this->sspConfiguration, $template); + + $templateInstance->getLocalization()->addModuleDomain(ModuleConfiguration::MODULE_NAME); + $templateInstance->getLocalization()->addAttributeDomains(); + + return $templateInstance; + } } diff --git a/src/ModuleConfiguration.php b/src/ModuleConfiguration.php index 71b33fd5600851385f5102b6be977a6163e85449..6b4e9abe03c9eeae99c9348f622c1be87526207e 100644 --- a/src/ModuleConfiguration.php +++ b/src/ModuleConfiguration.php @@ -16,6 +16,8 @@ use Throwable; class ModuleConfiguration { + public const MODULE_NAME = 'accounting'; + /** * Default file name for module configuration. Can be overridden, for example, for testing purposes. */ diff --git a/src/Providers/Builders/AuthenticationDataProviderBuilder.php b/src/Providers/Builders/AuthenticationDataProviderBuilder.php index a8b2bc374d1ebd60e26e15f651a48b14d531a856..121bc6125edda122fc716d8a55103f77b180b85b 100644 --- a/src/Providers/Builders/AuthenticationDataProviderBuilder.php +++ b/src/Providers/Builders/AuthenticationDataProviderBuilder.php @@ -26,8 +26,10 @@ class AuthenticationDataProviderBuilder /** * @throws Exception */ - public function build(string $class): AuthenticationDataProviderInterface - { + public function build( + string $class, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER + ): AuthenticationDataProviderInterface { try { // Make sure that the class implements proper interface if (!is_subclass_of($class, AuthenticationDataProviderInterface::class)) { @@ -44,7 +46,8 @@ class AuthenticationDataProviderBuilder $store = InstanceBuilderUsingModuleConfigurationHelper::build( $class, $this->moduleConfiguration, - $this->logger + $this->logger, + [$connectionType] ); } catch (Throwable $exception) { $message = sprintf('Error building instance for class %s. Error was: %s', $class, $exception->getMessage()); diff --git a/src/Providers/Interfaces/AuthenticationDataProviderInterface.php b/src/Providers/Interfaces/AuthenticationDataProviderInterface.php index b5e52c0896321c541e7e00759fcf9b2ce88e6bf2..8c60297dcefb758df57af9fae386a56963cf58ef 100644 --- a/src/Providers/Interfaces/AuthenticationDataProviderInterface.php +++ b/src/Providers/Interfaces/AuthenticationDataProviderInterface.php @@ -12,9 +12,13 @@ use SimpleSAML\Module\accounting\ModuleConfiguration; interface AuthenticationDataProviderInterface extends BuildableUsingModuleConfigurationInterface { - public static function build(ModuleConfiguration $moduleConfiguration, LoggerInterface $logger): self; + public static function build( + ModuleConfiguration $moduleConfiguration, + LoggerInterface $logger, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER + ): self; public function getConnectedServiceProviders(string $userIdentifier): ConnectedServiceProvider\Bag; - public function getActivity(string $userIdentifier): Activity\Bag; + public function getActivity(string $userIdentifier, int $maxResults, int $firstResult): Activity\Bag; } diff --git a/src/Services/HelpersManager.php b/src/Services/HelpersManager.php index f20ddc10612e584f09e496cd51995019b2395c03..43b85fecdd5b25355bfa366b115dd1b55022927e 100644 --- a/src/Services/HelpersManager.php +++ b/src/Services/HelpersManager.php @@ -7,12 +7,14 @@ namespace SimpleSAML\Module\accounting\Services; use SimpleSAML\Module\accounting\Helpers\DateTimeHelper; use SimpleSAML\Module\accounting\Helpers\EnvironmentHelper; use SimpleSAML\Module\accounting\Helpers\RandomHelper; +use SimpleSAML\Module\accounting\Helpers\ModuleRoutesHelper; class HelpersManager { protected static ?DateTimeHelper $dateTimeHelper; protected static ?EnvironmentHelper $environmentHelper; protected static ?RandomHelper $randomHelper; + protected static ?ModuleRoutesHelper $routesHelper; public function getDateTimeHelper(): DateTimeHelper { @@ -28,4 +30,9 @@ class HelpersManager { return self::$randomHelper ??= new RandomHelper(); } + + public function getModuleRoutesHelper(): ModuleRoutesHelper + { + return self::$routesHelper ??= new ModuleRoutesHelper(); + } } diff --git a/src/Stores/Bases/DoctrineDbal/AbstractStore.php b/src/Stores/Bases/DoctrineDbal/AbstractStore.php index 1ff76100f412bcbfb810863b8f53d413307a6de8..f560fac6fd5f0fbcf9d01d4bd929681058cb3684 100644 --- a/src/Stores/Bases/DoctrineDbal/AbstractStore.php +++ b/src/Stores/Bases/DoctrineDbal/AbstractStore.php @@ -30,12 +30,14 @@ abstract class AbstractStore implements BuildableUsingModuleConfigurationInterfa ModuleConfiguration $moduleConfiguration, LoggerInterface $logger, Factory $connectionFactory, - string $connectionKey = null + string $connectionKey = null, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER ) { $this->moduleConfiguration = $moduleConfiguration; $this->logger = $logger; - $connectionKey = $connectionKey ?? $moduleConfiguration->getClassConnectionKey($this->getSelfClass()); + $connectionKey = $connectionKey ?? + $moduleConfiguration->getClassConnectionKey($this->getSelfClass(), $connectionType); $this->connection = $connectionFactory->buildConnection($connectionKey); $this->migrator = $connectionFactory->buildMigrator($this->connection); } diff --git a/src/Stores/Builders/Bases/AbstractStoreBuilder.php b/src/Stores/Builders/Bases/AbstractStoreBuilder.php index adadc9d4640df3a4ef8edda41b5d6dc5da4c1b9c..7e96d3fc0d6b1f0191935f098238ea60f6a95d97 100644 --- a/src/Stores/Builders/Bases/AbstractStoreBuilder.php +++ b/src/Stores/Builders/Bases/AbstractStoreBuilder.php @@ -25,7 +25,11 @@ abstract class AbstractStoreBuilder $this->logger = $logger; } - abstract public function build(string $class, string $connectionKey = null): StoreInterface; + abstract public function build( + string $class, + string $connectionKey = null, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER + ): StoreInterface; /** * @throws StoreException diff --git a/src/Stores/Builders/DataStoreBuilder.php b/src/Stores/Builders/DataStoreBuilder.php index e9e1689f3c6829bacca7bdf411e1b6053ea02ad8..857b447f91ed1e51a7f61752e4023b231efffa94 100644 --- a/src/Stores/Builders/DataStoreBuilder.php +++ b/src/Stores/Builders/DataStoreBuilder.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace SimpleSAML\Module\accounting\Stores\Builders; use SimpleSAML\Module\accounting\Exceptions\StoreException; +use SimpleSAML\Module\accounting\ModuleConfiguration\ConnectionType; use SimpleSAML\Module\accounting\Stores\Interfaces\DataStoreInterface; class DataStoreBuilder extends Bases\AbstractStoreBuilder @@ -12,8 +13,11 @@ class DataStoreBuilder extends Bases\AbstractStoreBuilder /** * @throws StoreException */ - public function build(string $class, string $connectionKey = null): DataStoreInterface - { + public function build( + string $class, + string $connectionKey = null, + string $connectionType = ConnectionType::MASTER + ): DataStoreInterface { if (!is_subclass_of($class, DataStoreInterface::class)) { throw new StoreException( sprintf('Class \'%s\' does not implement interface \'%s\'.', $class, DataStoreInterface::class) @@ -21,7 +25,7 @@ class DataStoreBuilder extends Bases\AbstractStoreBuilder } /** @var DataStoreInterface $store */ - $store = $this->buildGeneric($class, [$connectionKey]); + $store = $this->buildGeneric($class, [$connectionKey, $connectionType]); return $store; } diff --git a/src/Stores/Builders/JobsStoreBuilder.php b/src/Stores/Builders/JobsStoreBuilder.php index 401e524d6e687f9711226792919cbceefc6275d7..9ad37849728be1192c9873e36f6326b00e641d45 100644 --- a/src/Stores/Builders/JobsStoreBuilder.php +++ b/src/Stores/Builders/JobsStoreBuilder.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace SimpleSAML\Module\accounting\Stores\Builders; use SimpleSAML\Module\accounting\Exceptions\StoreException; +use SimpleSAML\Module\accounting\ModuleConfiguration\ConnectionType; use SimpleSAML\Module\accounting\Stores\Interfaces\JobsStoreInterface; use function sprintf; @@ -14,8 +15,11 @@ class JobsStoreBuilder extends Bases\AbstractStoreBuilder /** * @throws StoreException */ - public function build(string $class, string $connectionKey = null): JobsStoreInterface - { + public function build( + string $class, + string $connectionKey = null, + string $connectionType = ConnectionType::MASTER + ): JobsStoreInterface { if (!is_subclass_of($class, JobsStoreInterface::class)) { throw new StoreException( sprintf('Class \'%s\' does not implement interface \'%s\'.', $class, JobsStoreInterface::class) @@ -25,7 +29,7 @@ class JobsStoreBuilder extends Bases\AbstractStoreBuilder $connectionKey = $connectionKey ?? $this->moduleConfiguration->getClassConnectionKey($class); /** @var JobsStoreInterface $store */ - $store = $this->buildGeneric($class, [$connectionKey]); + $store = $this->buildGeneric($class, [$connectionKey, $connectionType]); return $store; } diff --git a/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store.php b/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store.php index 543d007dd9c451614b5284fb08f62d62ecb5f35e..aecebb226923ceef769a2abac1e38ae5cee2a0f4 100644 --- a/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store.php +++ b/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store.php @@ -34,9 +34,10 @@ class Store extends AbstractStore implements DataStoreInterface LoggerInterface $logger, Factory $connectionFactory, string $connectionKey = null, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER, Repository $repository = null ) { - parent::__construct($moduleConfiguration, $logger, $connectionFactory, $connectionKey); + parent::__construct($moduleConfiguration, $logger, $connectionFactory, $connectionKey, $connectionType); $this->repository = $repository ?? new Repository($this->connection, $this->logger); } @@ -48,13 +49,15 @@ class Store extends AbstractStore implements DataStoreInterface public static function build( ModuleConfiguration $moduleConfiguration, LoggerInterface $logger, - string $connectionKey = null + string $connectionKey = null, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER ): self { return new self( $moduleConfiguration, $logger, new Factory($moduleConfiguration, $logger), - $connectionKey + $connectionKey, + $connectionType ); } @@ -574,10 +577,10 @@ class Store extends AbstractStore implements DataStoreInterface /** * @throws StoreException */ - public function getActivity(string $userIdentifierHashSha256): Activity\Bag + public function getActivity(string $userIdentifierHashSha256, int $maxResults, int $firstResult): Activity\Bag { // TODO mivanci pagination - $results = $this->repository->getActivity($userIdentifierHashSha256); + $results = $this->repository->getActivity($userIdentifierHashSha256, $maxResults, $firstResult); $activityBag = new Activity\Bag(); diff --git a/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/Repository.php b/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/Repository.php index c3c41bd7aac393e9274ec46d05500366a16e728b..976837ca24ce5d01e3d89f3831ef884d98f6bae8 100644 --- a/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/Repository.php +++ b/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/Repository.php @@ -951,7 +951,7 @@ class Repository /** * @throws StoreException */ - public function getActivity(string $userIdentifierHashSha256): array + public function getActivity(string $userIdentifierHashSha256, int $maxResults, int $firstResult): array { try { $authenticationEventsQueryBuilder = $this->connection->dbal()->createQueryBuilder(); @@ -1045,7 +1045,9 @@ class Repository TableConstants::TABLE_ALIAS_AUTHENTICATION_EVENT . '.' . TableConstants::TABLE_AUTHENTICATION_EVENT_COLUMN_NAME_ID, 'DESC' - ); + ) + ->setMaxResults($maxResults) + ->setFirstResult($firstResult); return $authenticationEventsQueryBuilder->executeQuery()->fetchAllAssociative(); } catch (\Throwable $exception) { diff --git a/src/Stores/Interfaces/DataStoreInterface.php b/src/Stores/Interfaces/DataStoreInterface.php index 81bcdcebf670d4079eb5707ee6c1ce00bc0fc297..8b5e0e5031e6b6dd47f394c49c2d01a3e1d16cc9 100644 --- a/src/Stores/Interfaces/DataStoreInterface.php +++ b/src/Stores/Interfaces/DataStoreInterface.php @@ -22,5 +22,5 @@ interface DataStoreInterface extends StoreInterface public function getConnectedOrganizations(string $userIdentifierHashSha256): ConnectedServiceProvider\Bag; - public function getActivity(string $userIdentifierHashSha256): Activity\Bag; + public function getActivity(string $userIdentifierHashSha256, int $maxResults, int $firstResult): Activity\Bag; } diff --git a/src/Stores/Jobs/DoctrineDbal/Store.php b/src/Stores/Jobs/DoctrineDbal/Store.php index 7bdbeebb01e87d5ad24695765c3a917aa916f2d6..55ba996500b70e072041c8302b62345424a6f001 100644 --- a/src/Stores/Jobs/DoctrineDbal/Store.php +++ b/src/Stores/Jobs/DoctrineDbal/Store.php @@ -31,10 +31,11 @@ class Store extends AbstractStore implements JobsStoreInterface LoggerInterface $logger, Factory $connectionFactory, string $connectionKey = null, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER, Repository $jobsRepository = null, Repository $failedJobsRepository = null ) { - parent::__construct($moduleConfiguration, $logger, $connectionFactory, $connectionKey); + parent::__construct($moduleConfiguration, $logger, $connectionFactory, $connectionKey, $connectionType); $this->prefixedTableNameJobs = $this->connection->preparePrefixedTableName(TableConstants::TABLE_NAME_JOB); $this->prefixedTableNameFailedJobs = $this->connection @@ -132,13 +133,15 @@ class Store extends AbstractStore implements JobsStoreInterface public static function build( ModuleConfiguration $moduleConfiguration, LoggerInterface $logger, - string $connectionKey = null + string $connectionKey = null, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER ): self { return new self( $moduleConfiguration, $logger, new Factory($moduleConfiguration, $logger), - $connectionKey + $connectionKey, + $connectionType ); } diff --git a/src/Trackers/Authentication/DoctrineDbal/Versioned/Tracker.php b/src/Trackers/Authentication/DoctrineDbal/Versioned/Tracker.php index 3a9c8d2a06f7fb158143a28af2393e200fa5a0d7..6c70e4c9a4582c9f73b9a9fe0cc4a4b034a87608 100644 --- a/src/Trackers/Authentication/DoctrineDbal/Versioned/Tracker.php +++ b/src/Trackers/Authentication/DoctrineDbal/Versioned/Tracker.php @@ -25,6 +25,7 @@ class Tracker implements AuthenticationDataTrackerInterface, AuthenticationDataP public function __construct( ModuleConfiguration $moduleConfiguration, LoggerInterface $logger, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER, DataStoreInterface $dataStore = null ) { $this->moduleConfiguration = $moduleConfiguration; @@ -33,14 +34,19 @@ class Tracker implements AuthenticationDataTrackerInterface, AuthenticationDataP // Use provided store or initialize default store for this tracker. $this->dataStore = $dataStore ?? (new DataStoreBuilder($this->moduleConfiguration, $this->logger)) - ->build(Store::class, $this->moduleConfiguration->getClassConnectionKey(self::class)); + ->build( + Store::class, + $this->moduleConfiguration->getClassConnectionKey(self::class), + $connectionType + ); } public static function build( ModuleConfiguration $moduleConfiguration, - LoggerInterface $logger + LoggerInterface $logger, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER ): self { - return new self($moduleConfiguration, $logger); + return new self($moduleConfiguration, $logger, $connectionType); } public function process(Event $authenticationEvent): void @@ -55,6 +61,11 @@ class Tracker implements AuthenticationDataTrackerInterface, AuthenticationDataP public function runSetup(): void { + if (! $this->needsSetup()) { + $this->logger->warning('Run setup called, however setup is not needed.'); + return; + } + $this->dataStore->runSetup(); } @@ -64,9 +75,9 @@ class Tracker implements AuthenticationDataTrackerInterface, AuthenticationDataP return $this->dataStore->getConnectedOrganizations($userIdentifierHashSha256); } - public function getActivity(string $userIdentifier): Activity\Bag + public function getActivity(string $userIdentifier, int $maxResults, int $firstResult): Activity\Bag { $userIdentifierHashSha256 = HashHelper::getSha256($userIdentifier); - return $this->dataStore->getActivity($userIdentifierHashSha256); + return $this->dataStore->getActivity($userIdentifierHashSha256, $maxResults, $firstResult); } } diff --git a/templates/admin/configuration/status.twig b/templates/admin/configuration/status.twig index 1ce05e9439de2df6715aa22048810fe8ba3ea62f..43ea6c53d089f104310d703b96d55d3e35beeee6 100644 --- a/templates/admin/configuration/status.twig +++ b/templates/admin/configuration/status.twig @@ -5,10 +5,6 @@ {% extends "base.twig" %} -{% block preload %} - <link rel="stylesheet" href="{{ asset('css/accounting.css', 'accounting') }}"> -{% endblock %} - {% block content %} <h2>{{ pagetitle }} </h2> @@ -21,10 +17,21 @@ <strong>{{ 'User ID Attribute Name'|trans }}</strong>: {{ moduleConfiguration.getUserIdAttributeName }} </li> <li> - <strong>{{ 'Accounting Processing Type'|trans }}</strong>: {{ moduleConfiguration.getAccountingProcessingType }} + <strong>{{ 'Accounting Processing Type'|trans }}</strong>: + {{ moduleConfiguration.getAccountingProcessingType }} + </li> + <li> + <strong>{{ 'Default Data Tracker and Provider Class'|trans }}</strong>: + {{ moduleConfiguration.getDefaultDataTrackerAndProviderClass }} + </li> + <li> + <strong>{{ 'Tracker and Provider Setup Needed'|trans }}</strong>: + {{ defaultDataTrackerAndProvider.needsSetup ? 'Yes'|trans : 'No'|trans }} </li> </ul> +{# TODO mivanci setup for additional trackers#} + {% if moduleConfiguration.getAccountingProcessingType == 'asynchronous' %} <ul> <li> @@ -44,4 +51,17 @@ <p>{{ 'Could not initialize module configuration.'|trans }}</p> {% endif %} + <br> + + {% if setupNeeded %} + <p>{{ 'Run setup before using the module.'|trans }}</p> + <a class="pure-button pure-button-warning" href="?runSetup=1">{{ 'Run Setup'|trans }}</a> + {% else %} + <p> + {{ 'Everything seems good to go.'|trans }} + <br> + <br> + {{ ' Profile page URL is'|trans }}: <a href="{{ profilePageUri }}">{{ profilePageUri }}</a> + </p> + {% endif %} {% endblock %} diff --git a/templates/base.twig b/templates/base.twig new file mode 100644 index 0000000000000000000000000000000000000000..4188e89210d503ea07f7f7d09c59bd567a33ed6b --- /dev/null +++ b/templates/base.twig @@ -0,0 +1,44 @@ + +{% extends "base.twig" %} + +{% block preload %} +{# TODO mivanci apply new CSS from Mihaly#} +{# <link rel="stylesheet" href="{{ asset('css/src/default.css', 'accounting') }}">#} + <link rel="stylesheet" href="{{ asset('css/src/custom.css', 'accounting') }}"> +{% endblock %} + +{% block contentwrapper %} + <div class="pure-g"> + <div class="pure-u-1"> + {% include '@accounting/includes/_header.twig' %} + </div> + </div> + + <div class="pure-g"> + <div class="pure-u-1-5"> + {% include '@accounting/includes/_navigation.twig' %} + </div> + <div class="pure-u-4-5"> + {{ block('content') }} + </div> + </div> +{% endblock %} + +{% block footer %} + <footer style="text-align: center;"> + <div> + {% trans %} + As part of the GÉANT 2020 Framework Partnership Agreement (FPA), the project receives funding + from the European Union’s Horizon 2020 research and innovation programme under Grant + Agreement No. 856726 (GN4-3). + {% endtrans %} + </div> + </footer> + + {{ parent() }} +{% endblock %} + +{% block postload %} +{# TODO mivanci add JS#} +{# <script src="{{ asset('js/src/default.js', 'accounting') }}"></script>#} +{% endblock %} diff --git a/templates/includes/_header.twig b/templates/includes/_header.twig new file mode 100644 index 0000000000000000000000000000000000000000..37867ddf5c12084eadb47633af4bdb889340d359 --- /dev/null +++ b/templates/includes/_header.twig @@ -0,0 +1,8 @@ +<header> + <div id="logo"> + <img src="{{ asset('css/src/icons/fppp-logo.svg', 'accounting') }}" alt="Profile Page Logo"> + </div> + <label for="nav-toggle" class="nav-toggle-label"> + <span></span> + </label> +</header> \ No newline at end of file diff --git a/templates/includes/_js-accordion.twig b/templates/includes/_js-accordion.twig new file mode 100644 index 0000000000000000000000000000000000000000..6f27acee812e27151daeaa19669471a1d8e60181 --- /dev/null +++ b/templates/includes/_js-accordion.twig @@ -0,0 +1,23 @@ +<script> + (function () { + var acc = document.getElementsByClassName("accordion"); + var i; + + for (i = 0; i < acc.length; i++) { + acc[i].addEventListener("click", function () { + /* Toggle between adding and removing the "active" class, + to highlight the button that controls the panel */ + this.classList.toggle("active"); + + /* Toggle between hiding and showing the active panel */ + var panel = this.nextElementSibling; + + if (panel.style.display === "table-row") { + panel.style.display = "none"; + } else { + panel.style.display = "table-row"; + } + }); + } + })(); +</script> \ No newline at end of file diff --git a/templates/includes/_navigation.twig b/templates/includes/_navigation.twig new file mode 100644 index 0000000000000000000000000000000000000000..1f34eb9093410b7defcdf86746529e9d2c24ce34 --- /dev/null +++ b/templates/includes/_navigation.twig @@ -0,0 +1,28 @@ +<div class="pure-menu"> + <span class="pure-menu-heading"></span> + <ul class="pure-menu-list"> +{# asset icon example #} +{# <li class="pure-menu-item">#} +{# <a href="personal-data">#} +{# <span class="navicon">#} +{# <img src="{{ asset('css/src/icons/prof-page.svg', 'accounting') }}"#} +{# alt="Personal Data Icon">#} +{# </span>#} +{# <span>Personal Data</span>#} +{# </a>#} +{# </li>#} + + <li class="pure-menu-item {% if pageMenuItem is defined and pageMenuItem == 'personal-data' %}pure-menu-selected{% endif %}"> + <a href="personal-data" class="pure-menu-link">Personal Data</a> + </li> + <li class="pure-menu-item {% if pageMenuItem is defined and pageMenuItem == 'connected-organizations' %}pure-menu-selected{% endif %}"> + <a href="connected-organizations" class="pure-menu-link">Connected Organizations</a> + </li> + <li class="pure-menu-item {% if pageMenuItem is defined and pageMenuItem == 'activity' %} pure-menu-selected{% endif %}"> + <a href="activity" class="pure-menu-link">Activity</a> + </li> + <li class="pure-menu-item"> + <a href="#" class="pure-menu-link">Log Out</a> + </li> + </ul> +</div> \ No newline at end of file diff --git a/templates/user/activity.twig b/templates/user/activity.twig new file mode 100644 index 0000000000000000000000000000000000000000..c505f4349b6a2125611e326c1b5dafce104a7db7 --- /dev/null +++ b/templates/user/activity.twig @@ -0,0 +1,66 @@ +{# @var activityBag \SimpleSAML\Module\accounting\Entities\Activity\Bag #} +{# @var connectedServiceProvider \SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider #} + +{% extends "@accounting/base.twig" %} + +{% set pagetitle = 'Activity'|trans %} + +{% set pageMenuItem = 'activity' %} + +{% block content %} + + <h2>{{ pagetitle }} </h2> + + <table class="pure-table pure-table-striped pure-table-attributes"> + <thead> + <tr> + <th><strong>{{ 'Time'|trans }}</strong></th> + <th><strong>{{ 'Access'|trans }}</strong></th> + <th><strong>{{ 'Sent data'|trans }}</strong></th> + </tr> + </thead> + <tbody> + {% for activity in activityBag.getAll %} + <tr class="accordion"> + <td>{{ activity.getHappenedAt|date() }}</td> + <td>{{ activity.getServiceProvider.getName }}</td> + <td> + {% for name in activity.getUser.getAttributes|keys %} + {{ name|trans }}{% if not loop.last %}, {% endif %} + {% endfor %} + </td> + </tr> + <tr class="panel"> + <td colspan="3"> + <strong>{{ 'Information transfered to service'|trans }}</strong> + <ul> + {% for name, value in activity.getUser.getAttributes %} + <li> + {{ name|trans }}: {{ value|join(', ') }} + </li> + {% endfor %} + </ul> + </td> + </tr> + {% endfor %} + </tbody> + </table> + <br> + <div class="center"> + <div class="pagination"> + {% if page > 1 %} + <a href="?page={{ page - 1 }}">❮</a> + {% endif %} + + {% if activityBag.getAll|length == maxResults %} + <a href="?page={{ page + 1 }}">❯</a> + {% endif %} + </div> + </div> + +{% endblock %} + +{% block postload %} + {{ parent() }} + {% include '@accounting/includes/_js-accordion.twig' %} +{% endblock %} \ No newline at end of file diff --git a/templates/user/connected-organizations.twig b/templates/user/connected-organizations.twig index a05508ea7746936b5eacf9dad7a6f3c1d6212c9a..0229fc575914a778db484bf43d9b5b3cc70d339f 100644 --- a/templates/user/connected-organizations.twig +++ b/templates/user/connected-organizations.twig @@ -1,24 +1,66 @@ -{# @var moduleConfiguration \SimpleSAML\Module\accounting\ModuleConfiguration #} +{# @var connectedServiceProviderBag \SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider\Bag #} +{# @var connectedServiceProvider \SimpleSAML\Module\accounting\Entities\ConnectedServiceProvider #} -{% set pagetitle = 'Connected Organizations'|trans %} -{% set frontpage_section = 'main' %} +{% extends "@accounting/base.twig" %} -{% extends "base.twig" %} +{% set pagetitle = 'Connected organizations'|trans %} -{% block preload %} - <link rel="stylesheet" href="{{ asset('css/accounting.css', 'accounting') }}"> -{% endblock %} +{% set pageMenuItem = 'connected-organizations' %} {% block content %} <h2>{{ pagetitle }} </h2> + <table class="pure-table pure-table-striped pure-table-attributes"> + <thead> + <tr> + <th><strong>{{ 'Name'|trans }}</strong></th> + <th><strong>{{ 'All access'|trans }}</strong></th> + <th><strong>{{ 'Last access'|trans }}</strong></th> + </tr> + </thead> + <tbody> + {% for connectedServiceProvider in connectedServiceProviderBag.getAll %} + <tr class="accordion"> + <td>{{ connectedServiceProvider.getServiceProvider.getName|e }}</td> + <td>{{ connectedServiceProvider.getNumberOfAuthentications|e }}</td> + <td>{{ connectedServiceProvider.getLastAuthenticationAt|date() }}</td> + </tr> + <tr class="panel"> + <td colspan="3"> + <strong>{{ 'Service details'|trans }}</strong> + <ul> + <li>{{ 'Entity ID'|trans }}: {{ connectedServiceProvider.getServiceProvider.getEntityId|e }}</li> + <li>{{ 'Description'|trans }}: {{ connectedServiceProvider.getServiceProvider.getDescription|e|default(' / ') }}</li> + </ul> + <strong>{{ 'Information transfered to service'|trans }}</strong> + <ul> + {% for name, value in connectedServiceProvider.getUser.getAttributes %} + <li> + {{ name|trans }}: {{ value|join(', ') }} + </li> + {% endfor %} + </ul> - <ul> - {% for name, value in normalizedAttributes %} - <li><strong>{{ name }}</strong>: {{ value }}</li> + <strong>{{ 'Login details'|trans }}</strong> + <ul> + <li> + {{ 'First access'|trans }}: {{ connectedServiceProvider.getFirstAuthenticationAt|date() }} + </li> + <li> + {{ 'Last access'|trans }}: {{ connectedServiceProvider.getLastAuthenticationAt|date() }} + </li> + </ul> + </td> + </tr> {% endfor %} - </ul> + </tbody> + </table> + +{% endblock %} +{% block postload %} + {{ parent() }} + {% include '@accounting/includes/_js-accordion.twig' %} {% endblock %} diff --git a/templates/user/personal-data.twig b/templates/user/personal-data.twig index 51a0921f26e8de58817e6ee5a1f7f14758d11716..9aa3bc58c3bf220b2adf045627348591fdb1de80 100644 --- a/templates/user/personal-data.twig +++ b/templates/user/personal-data.twig @@ -1,26 +1,35 @@ -{# @var moduleConfiguration \SimpleSAML\Module\accounting\ModuleConfiguration #} -{% set pagetitle = 'Personal Data'|trans %} -{% set frontpage_section = 'main' %} +{% extends "@accounting/base.twig" %} -{% extends "base.twig" %} +{% set pagetitle = 'Personal Data'|trans %} -{% block preload %} - <link rel="stylesheet" href="{{ asset('css/accounting.css', 'accounting') }}"> -{% endblock %} +{% set pageMenuItem = 'personal-data' %} {% block content %} <h2>{{ pagetitle }} </h2> - <p> - {% trans %}This is what we know about you... Lorem ipsum...{% endtrans %} - </p> - - <ul> - {% for name, value in normalizedAttributes %} - <li><strong>{{ name }}</strong>: {{ value }}</li> - {% endfor %} - </ul> + <section id="banner"> + <div> + {% trans %}This is what we know about you...{% endtrans %} + </div> + </section> + + <table class="pure-table pure-table-striped pure-table-attributes"> + <thead> + <tr> + <th><strong>Attribute</strong></th> + <th><strong>Your value</strong></th> + </tr> + </thead> + <tbody> + {% for name, value in normalizedAttributes %} + <tr> + <td>{{ name|trans }}</td> + <td>{{ value }}</td> + </tr> + {% endfor %} + </tbody> + </table> {% endblock %} diff --git a/tests/src/Stores/Builders/JobsStoreBuilderTest.php b/tests/src/Stores/Builders/JobsStoreBuilderTest.php index fb212835e96b6a2953d8514c4b1eb6a41edcf508..9b954a2248b22984f39fb59a4ea46de3c8042598 100644 --- a/tests/src/Stores/Builders/JobsStoreBuilderTest.php +++ b/tests/src/Stores/Builders/JobsStoreBuilderTest.php @@ -58,9 +58,12 @@ class JobsStoreBuilderTest extends TestCase /** @psalm-suppress InvalidArgument */ $storeBuilder = new class ($moduleConfigurationStub, $this->loggerStub) extends AbstractStoreBuilder { - public function build(string $class, string $connectionKey = null): StoreInterface - { - return $this->buildGeneric($class, [$connectionKey]); + public function build( + string $class, + string $connectionKey = null, + string $connectionType = ModuleConfiguration\ConnectionType::MASTER + ): StoreInterface { + return $this->buildGeneric($class, [$connectionKey, $connectionType]); } }; diff --git a/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/RepositoryTest.php b/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/RepositoryTest.php index 2cd94b37a3698ae46805ac95ce47662e7e84ad4b..ee2f160a3a3015c99e01bdcd4ae1e7300625ca65 100644 --- a/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/RepositoryTest.php +++ b/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/Store/RepositoryTest.php @@ -639,15 +639,15 @@ class RepositoryTest extends TestCase $this->repository->insertAuthenticationEvent($idpSpUserVersionId, $this->createdAt, $this->createdAt); - $resultArray = $this->repository->getActivity($this->userIdentifierHash); + $resultArray = $this->repository->getActivity($this->userIdentifierHash, 10, 0); $this->assertCount(1, $resultArray); $this->repository->insertAuthenticationEvent($idpSpUserVersionId, $this->createdAt, $this->createdAt); - $resultArray = $this->repository->getActivity($this->userIdentifierHash); + $resultArray = $this->repository->getActivity($this->userIdentifierHash, 10, 0); $this->assertCount(2, $resultArray); $this->repository->insertAuthenticationEvent($idpSpUserVersionId, $this->createdAt, $this->createdAt); - $resultArray = $this->repository->getActivity($this->userIdentifierHash); + $resultArray = $this->repository->getActivity($this->userIdentifierHash, 10, 0); $this->assertCount(3, $resultArray); // Simulate another SP @@ -670,7 +670,7 @@ class RepositoryTest extends TestCase (int)$idpSpUserVersionResult[Store\TableConstants::TABLE_IDP_SP_USER_VERSION_COLUMN_NAME_ID]; $this->repository->insertAuthenticationEvent($idpSpUserVersionId, $this->createdAt, $this->createdAt); - $resultArray = $this->repository->getActivity($this->userIdentifierHash); + $resultArray = $this->repository->getActivity($this->userIdentifierHash, 10, 0); $this->assertCount(4, $resultArray); // Simulate a change in user attributes @@ -682,6 +682,6 @@ class RepositoryTest extends TestCase $repository = new Repository($this->connectionStub, $this->loggerStub); $this->expectException(StoreException::class); - $repository->getActivity($this->userIdentifierHash); + $repository->getActivity($this->userIdentifierHash, 10, 0); } } diff --git a/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/StoreTest.php b/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/StoreTest.php index b7506f38917105ee8febbb2df59944ce6f45f2e9..9919d1faf25c5b7039c63054075fe269bf2501ae 100644 --- a/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/StoreTest.php +++ b/tests/src/Stores/Data/Authentication/DoctrineDbal/Versioned/StoreTest.php @@ -233,6 +233,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -253,6 +254,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -271,6 +273,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -291,6 +294,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -309,6 +313,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -329,6 +334,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -347,6 +353,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -367,6 +374,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -387,6 +395,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -404,6 +413,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -424,6 +434,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -442,6 +453,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -462,6 +474,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -480,6 +493,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -500,6 +514,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -519,6 +534,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -538,6 +554,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -560,6 +577,7 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); @@ -577,10 +595,11 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); - $activityBag = $store->getActivity('test'); + $activityBag = $store->getActivity('test', 10, 0); $this->assertEmpty($activityBag->getAll()); } @@ -596,10 +615,11 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); - $activityBag = $store->getActivity('test'); + $activityBag = $store->getActivity('test', 10, 0); $this->assertNotEmpty($activityBag->getAll()); } @@ -618,10 +638,11 @@ class StoreTest extends TestCase $this->loggerMock, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $this->repositoryStub ); $this->expectException(StoreException::class); - $store->getActivity('test'); + $store->getActivity('test', 10, 0); } } diff --git a/tests/src/Stores/Jobs/DoctrineDbal/StoreTest.php b/tests/src/Stores/Jobs/DoctrineDbal/StoreTest.php index 4949b3548f649e406ad3987fb215df8986350ea9..d4efbb85925d773f9e778e412b8b3be3776d22da 100644 --- a/tests/src/Stores/Jobs/DoctrineDbal/StoreTest.php +++ b/tests/src/Stores/Jobs/DoctrineDbal/StoreTest.php @@ -250,6 +250,7 @@ class StoreTest extends TestCase $this->loggerStub, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $repositoryStub ); $jobsStore->runSetup(); @@ -271,6 +272,7 @@ class StoreTest extends TestCase $this->loggerStub, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $repositoryStub ); $jobsStore->runSetup(); @@ -292,6 +294,7 @@ class StoreTest extends TestCase $this->loggerStub, $this->factoryStub, null, + ModuleConfiguration\ConnectionType::MASTER, $repositoryStub ); $jobsStore->runSetup(); diff --git a/tests/src/Trackers/Authentication/DoctrineDbal/Versioned/TrackerTest.php b/tests/src/Trackers/Authentication/DoctrineDbal/Versioned/TrackerTest.php index 00776a3cf5c01283cfb8a046e139d8a519d2026a..7f64ac971b218236af493c6d878aeb32eda7eef3 100644 --- a/tests/src/Trackers/Authentication/DoctrineDbal/Versioned/TrackerTest.php +++ b/tests/src/Trackers/Authentication/DoctrineDbal/Versioned/TrackerTest.php @@ -32,15 +32,15 @@ use SimpleSAML\Test\Module\accounting\Constants\ConnectionParameters; class TrackerTest extends TestCase { /** - * @var \PHPUnit\Framework\MockObject\Stub|ModuleConfiguration|ModuleConfiguration&\PHPUnit\Framework\MockObject\Stub + * @var \PHPUnit\Framework\MockObject\Stub|ModuleConfiguration */ protected $moduleConfigurationStub; /** - * @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface|LoggerInterface&\PHPUnit\Framework\MockObject\MockObject + * @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface */ protected $loggerMock; /** - * @var \PHPUnit\Framework\MockObject\MockObject|Store|Store&\PHPUnit\Framework\MockObject\MockObject + * @var \PHPUnit\Framework\MockObject\MockObject|Store */ protected $dataStoreMock; @@ -60,7 +60,12 @@ class TrackerTest extends TestCase { $this->assertInstanceOf( Tracker::class, - new Tracker($this->moduleConfigurationStub, $this->loggerMock, $this->dataStoreMock) + new Tracker( + $this->moduleConfigurationStub, + $this->loggerMock, + ModuleConfiguration\ConnectionType::MASTER, + $this->dataStoreMock + ) ); $this->assertInstanceOf( @@ -83,14 +88,19 @@ class TrackerTest extends TestCase ->with($authenticationEventStub); /** @psalm-suppress PossiblyInvalidArgument */ - $tracker = new Tracker($this->moduleConfigurationStub, $this->loggerMock, $this->dataStoreMock); + $tracker = new Tracker( + $this->moduleConfigurationStub, + $this->loggerMock, + ModuleConfiguration\ConnectionType::MASTER, + $this->dataStoreMock + ); $tracker->process($authenticationEventStub); } public function testSetupDependsOnDataStore(): void { - $this->dataStoreMock->expects($this->once()) + $this->dataStoreMock->expects($this->exactly(2)) ->method('needsSetup') ->willReturn(true); @@ -98,7 +108,12 @@ class TrackerTest extends TestCase ->method('runSetup'); /** @psalm-suppress PossiblyInvalidArgument */ - $tracker = new Tracker($this->moduleConfigurationStub, $this->loggerMock, $this->dataStoreMock); + $tracker = new Tracker( + $this->moduleConfigurationStub, + $this->loggerMock, + ModuleConfiguration\ConnectionType::MASTER, + $this->dataStoreMock + ); $this->assertTrue($tracker->needsSetup()); @@ -113,7 +128,12 @@ class TrackerTest extends TestCase ->willReturn($connectedOrganizationsBagStub); /** @psalm-suppress PossiblyInvalidArgument */ - $tracker = new Tracker($this->moduleConfigurationStub, $this->loggerMock, $this->dataStoreMock); + $tracker = new Tracker( + $this->moduleConfigurationStub, + $this->loggerMock, + ModuleConfiguration\ConnectionType::MASTER, + $this->dataStoreMock + ); $this->assertInstanceOf( ConnectedServiceProvider\Bag::class, @@ -128,11 +148,16 @@ class TrackerTest extends TestCase ->method('getActivity') ->willReturn($activityBag); - $tracker = new Tracker($this->moduleConfigurationStub, $this->loggerMock, $this->dataStoreMock); + $tracker = new Tracker( + $this->moduleConfigurationStub, + $this->loggerMock, + ModuleConfiguration\ConnectionType::MASTER, + $this->dataStoreMock + ); $this->assertInstanceOf( Activity\Bag::class, - $tracker->getActivity('test') + $tracker->getActivity('test', 10, 0) ); } } diff --git a/www/assets/css/accounting.css b/www/assets/css/accounting.css deleted file mode 100644 index b7e4bd59ee1e9c2f391534308cb92ba6f885c4ac..0000000000000000000000000000000000000000 --- a/www/assets/css/accounting.css +++ /dev/null @@ -1,3 +0,0 @@ -.test table { - border: 1px solid #eee; -} \ No newline at end of file diff --git a/www/assets/css/src/custom.css b/www/assets/css/src/custom.css new file mode 100644 index 0000000000000000000000000000000000000000..cb8acd7af26be658c0754190f87531e2f12e9fce --- /dev/null +++ b/www/assets/css/src/custom.css @@ -0,0 +1,42 @@ +.center { + text-align: center; +} + +.pagination { + display: inline-block; +} + +.pagination a { + color: black; + float: left; + padding: 8px 16px; + text-decoration: none; + transition: background-color .3s; + border: 1px solid #ddd; +} + +.pagination a.active { + background-color: #4CAF50; + color: white; + border: 1px solid #4CAF50; +} + +.pagination a:hover:not(.active) {background-color: #ddd;} + + +.accordion { + cursor: pointer; + transition: 0.4s; + border-bottom: 1px solid #cbcbcb; +} + +.active, .accordion:hover { + background-color: #ccc; +} + +.panel { + display: none; + max-height: 0; + overflow: hidden; + transition: max-height 0.2s ease-out; +} \ No newline at end of file diff --git a/www/assets/css/src/default.css b/www/assets/css/src/default.css new file mode 100644 index 0000000000000000000000000000000000000000..4ce4350caee79661d1e61f124f9bad2dac4e4bb5 --- /dev/null +++ b/www/assets/css/src/default.css @@ -0,0 +1,358 @@ +:root { + /* */ + --main-text-c: #181E3C; + --main-bg-c: #F5F5F5; + + --heading-text-c: #5B6186; + + --caption-bg-c: #F0F2F9; + + --table-border: #F0F2F9; + + --nav-bg-c: #F8F8FC; + + --button-bg-c: #4859B2; + --button-text-c: #ffffff; + + --link-c: #4859B2; + + --main-font-family: Raleway; + --main-font-weight: 500; + --mainfont-size: 18pt; + + --table-font-size: 18pt; + + --large-font-size: 24px; +} + +/* raleway-300 - latin-ext_latin */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 300; + src: local(''), + url('fonts/raleway-v28-latin-ext_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('fonts/raleway-v28-latin-ext_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} +/* raleway-regular - latin-ext_latin */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 400; + src: local(''), + url('fonts/raleway-v28-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('fonts/raleway-v28-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} +/* raleway-500 - latin-ext_latin */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 500; + src: local(''), + url('fonts/raleway-v28-latin-ext_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('fonts/raleway-v28-latin-ext_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} +/* raleway-600 - latin-ext_latin */ +@font-face { + font-family: 'Raleway'; + font-style: normal; + font-weight: 600; + src: local(''), + url('fonts/raleway-v28-latin-ext_latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */ + url('fonts/raleway-v28-latin-ext_latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ +} + +/* ======================= */ +/* mobile-first body */ +/* ======================= */ + +/*body {*/ +/* display: grid;*/ +/* grid-template-rows: 4em auto auto auto auto;*/ +/* grid-template-columns: 1fr 18fr 1fr;*/ +/* grid-template-areas:*/ +/* "header header header"*/ +/* "nav nav nav"*/ +/* ". banner ."*/ +/* ". main ."*/ +/* "footer footer footer";*/ +/* min-height: 100vh;*/ +/* font-size: var(--main-font-size);*/ +/* font-family: var(--main-font-family);*/ +/* font-weight: var(--main-font-weight);*/ +/* margin: 0;*/ +/*}*/ + +/* ======================= */ +/* header and logo */ +/* ======================= */ + +header { + grid-area: header; + background-color: var(--nav-bg-c); + color: var(--link-c); + display: flex; + text-align: center; + width:100%; + z-index:999; + flex-direction: row; + align-items: center; + justify-content: flex-start; +} + +#logo { + /*margin-left: 2em;*/ +} + +/* ======================= */ +/* Nav with hamburger menu */ +/* ======================= */ + +#nav{ + grid-area: nav; +} + +nav { + width: 100%; + padding: 1em; + text-align: left; + display:none; + background-color: var(--nav-bg-c); +} + +nav ul { + margin: 0; + padding: 0; + list-style: none; + display: inline-flex; + flex-direction: column; + flex-wrap: wrap; + align-items: left; + justify-content: flex-end; +} + +nav li { + margin-left: 0.5em; + margin-right: 0.5em; + color: var(--alt-color); +} + +nav > ul > li { + font-variant: normal; + display: flex; + flex-direction: row; + align-items: center; + margin-top: 0.5em; +} + +nav > ul > li > a { + color: var(--banner-font-family); + text-decoration: none; + display: flex; + flex-direction: row; + justify-items: center; +} + +.nav-toggle { + display:none; +} + +.nav-toggle:checked ~ nav { + display: block; +} + +.nav-toggle:checked ~ div { + display: none; +} + +.nav-toggle-label { + margin-right: 1em; + margin-left: auto; + display: flex; + height: 100%; + align-items: center; + align-self: flex-end; +} + +.nav-toggle:not(:checked) ~ .nav-toggle-label { + margin-left: auto; +} + +.nav-toggle-label span, +.nav-toggle-label span:before, +.nav-toggle-label span:after { + display: block; + background: var(--link-c);; + height: 2px; + width: 2em; + position: relative; +} + +.nav-toggle-label span:before, +.nav-toggle-label span:after { + content: ''; + position: absolute; +} + +.nav-toggle-label span:before { + bottom: 7px; +} + +.nav-toggle-label span:after { + top: 7px; +} + +.navicon { + display: inline-grid; + justify-content: center; + align-content: center; + width: 2em; +} + +/* ======================= */ +/* Banner */ +/* ======================= */ +#banner { + grid-area: banner; +} + +#banner div { + color: var(--link-c); + background-color: var(--nav-bg-c); + margin: 2em; + padding-left: 1em; + padding-right: 1em; + padding-bottom: 1em; + padding-top: 2.5em; + + border-width: 1px; + border-style: solid; + border-color: var(--link-c); +} + +/* ======================= */ +/* Main */ +/* ======================= */ +#main{ + grid-area: main; +} + +/* ======================= */ +/* Table */ +/* ======================= */ +table { + margin:1em; + padding:1em; + margin-right: auto; + font-size: var(--table-font-size); + width: 100%; +} + +th { + text-align:left; + padding:0.5em; + word-wrap: break-word; + border-bottom: solid 1px var(--table-border); +} + +td { + text-align:left; + padding:0.5em; + word-wrap: break-word; + border-bottom: solid 1px var(--table-border); +} + +th a { + text-decoration:none; +} + +td a { + text-decoration: none; +} + +.dropdown { + float:right; +} + +/* ======================= */ +/* Footer */ +/* ======================= */ +/*footer {*/ +/* display: flex;*/ +/* text-align: center;*/ +/* width:100%;*/ +/* z-index:999;*/ +/* flex-direction: row;*/ +/* align-items: center;*/ +/* justify-content: flex-start;*/ +/* grid-area: footer;*/ +/* color: var(--link-c);*/ +/* background-color: var(--nav-bg-c);*/ +/*}*/ + +/*footer div {*/ +/* margin: 2em;*/ +/*}*/ + +/* ======================= */ +/* desktop provisions */ +/* ======================= */ +@media only screen and (min-width: 768px) { + /*body {*/ + /* display: grid;*/ + /* grid-template-rows: 4em auto auto auto;*/ + /* grid-template-columns: 3fr 0.5fr 16fr 0.5fr;*/ + /* grid-template-areas:*/ + /* "header header header header"*/ + /* "nav . banner ."*/ + /* "nav . main ."*/ + /* "nav footer footer footer";*/ + /* min-height: 100vh;*/ + /* font-size: var(--body-font-size);*/ + /* font-family: var(--main-font-family);*/ + /* font-weight: var(--main-font-weight);*/ + /* margin: 0;*/ + /*}*/ + + header { + background-color: var(--main-bg-c); + } + + #nav { + background-color: var(--nav-bg-c); + } + + nav { + width: 100%; + padding: 0em; + margin-left: 0em; + } + + nav > ul { + width: 100%; + } + + nav > ul > li { + font-variant: normal; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 1em; + } + + nav > ul > li > a { + width: 100%; + } + + nav > ul > li > a > span > img { + display: inline; + } + + .nav-toggle ~ nav { + display: block; + } + + .nav-toggle-label { + display: none; + } +} diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-300.woff b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-300.woff new file mode 100644 index 0000000000000000000000000000000000000000..dc1fdae677d4997655cbbe569035de51f2283ee4 Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-300.woff differ diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-300.woff2 b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-300.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..5c74b981a826de2286fead05d18752c0cd0fe787 Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-300.woff2 differ diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-500.woff b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-500.woff new file mode 100644 index 0000000000000000000000000000000000000000..90f9b9a12c51cd868aca772a613e2340384b0dc6 Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-500.woff differ diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-500.woff2 b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-500.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..902e197fceb48075a90088328383c444f32e9a19 Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-500.woff2 differ diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-600.woff b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-600.woff new file mode 100644 index 0000000000000000000000000000000000000000..7f9315eb18875ac0612c71f34cd4acbb161bb41f Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-600.woff differ diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-600.woff2 b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-600.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..977bba2f6a116b7e0f3896d067e3abd0df9a34b6 Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-600.woff2 differ diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-regular.woff b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..067a3fda39dc8080c117a8c8540438b43b106516 Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-regular.woff differ diff --git a/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-regular.woff2 b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..fb296a5863312faceb7d1f5af3ec9899744757d5 Binary files /dev/null and b/www/assets/css/src/fonts/raleway-v28-latin-ext_latin-regular.woff2 differ diff --git a/www/assets/css/src/icons/activity.svg b/www/assets/css/src/icons/activity.svg new file mode 100644 index 0000000000000000000000000000000000000000..d209dc1609b1d3e69ffb65a66f1a9bcdfc5ba8bc --- /dev/null +++ b/www/assets/css/src/icons/activity.svg @@ -0,0 +1,3 @@ +<svg width="26" height="20" viewBox="0 0 26 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M12.9974 12.4207L14.2807 9.5332L17.1682 8.24987L14.2807 6.96654L12.9974 4.07904L11.7141 6.96654L8.82656 8.24987L11.7141 9.5332L12.9974 12.4207ZM3.60573 16.679C3.13906 16.679 2.74045 16.5138 2.4099 16.1832C2.07934 15.8526 1.91406 15.4638 1.91406 15.0165V2.03737C1.91406 1.5707 2.07934 1.17209 2.4099 0.841537C2.74045 0.510981 3.13906 0.345703 3.60573 0.345703H22.3891C22.8557 0.345703 23.2543 0.510981 23.5849 0.841537C23.9155 1.17209 24.0807 1.5707 24.0807 2.03737V15.0165C24.0807 15.4638 23.9155 15.8526 23.5849 16.1832C23.2543 16.5138 22.8557 16.679 22.3891 16.679H3.60573ZM3.60573 15.3665H22.3891C22.4863 15.3665 22.5738 15.3276 22.6516 15.2499C22.7293 15.1721 22.7682 15.0943 22.7682 15.0165V2.03737C22.7682 1.94015 22.7293 1.85751 22.6516 1.78945C22.5738 1.7214 22.4863 1.68737 22.3891 1.68737H3.60573C3.50851 1.68737 3.42101 1.7214 3.34323 1.78945C3.26545 1.85751 3.22656 1.94015 3.22656 2.03737V15.0165C3.22656 15.0943 3.26545 15.1721 3.34323 15.2499C3.42101 15.3276 3.50851 15.3665 3.60573 15.3665ZM3.22656 15.3665V1.68737V15.3665ZM1.2724 19.5957C1.07795 19.5957 0.917535 19.5325 0.791146 19.4061C0.664757 19.2797 0.601562 19.1193 0.601562 18.9249C0.601562 18.7499 0.664757 18.5992 0.791146 18.4728C0.917535 18.3464 1.07795 18.2832 1.2724 18.2832H24.7224C24.9168 18.2832 25.0773 18.3464 25.2036 18.4728C25.33 18.5992 25.3932 18.7596 25.3932 18.954C25.3932 19.129 25.33 19.2797 25.2036 19.4061C25.0773 19.5325 24.9168 19.5957 24.7224 19.5957H1.2724Z" fill="black"/> +</svg> diff --git a/www/assets/css/src/icons/conn-orgs.svg b/www/assets/css/src/icons/conn-orgs.svg new file mode 100644 index 0000000000000000000000000000000000000000..9b497e85140b71c7a2c504e3a5c73ff0829bede0 --- /dev/null +++ b/www/assets/css/src/icons/conn-orgs.svg @@ -0,0 +1,3 @@ +<svg width="24" height="18" viewBox="0 0 24 18" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M11.3557 13.0833H12.6682V7.3375L15.1474 9.875L16.0807 8.9125L11.9682 4.82917L7.8849 8.9125L8.8474 9.875L11.3557 7.3375V13.0833ZM2.60573 17.75C2.13906 17.75 1.74045 17.5847 1.4099 17.2542C1.07934 16.9236 0.914062 16.525 0.914062 16.0583V1.94167C0.914062 1.475 1.07934 1.07639 1.4099 0.745834C1.74045 0.415278 2.13906 0.25 2.60573 0.25H21.3891C21.8557 0.25 22.2543 0.415278 22.5849 0.745834C22.9155 1.07639 23.0807 1.475 23.0807 1.94167V16.0583C23.0807 16.525 22.9155 16.9236 22.5849 17.2542C22.2543 17.5847 21.8557 17.75 21.3891 17.75H2.60573ZM2.60573 16.4375H21.3891C21.4863 16.4375 21.5738 16.3986 21.6516 16.3208C21.7293 16.2431 21.7682 16.1556 21.7682 16.0583V1.94167C21.7682 1.84444 21.7293 1.75694 21.6516 1.67917C21.5738 1.60139 21.4863 1.5625 21.3891 1.5625H2.60573C2.50851 1.5625 2.42101 1.60139 2.34323 1.67917C2.26545 1.75694 2.22656 1.84444 2.22656 1.94167V16.0583C2.22656 16.1556 2.26545 16.2431 2.34323 16.3208C2.42101 16.3986 2.50851 16.4375 2.60573 16.4375ZM2.22656 16.4375V1.5625V16.4375Z" fill="black"/> +</svg> diff --git a/www/assets/css/src/icons/download.svg b/www/assets/css/src/icons/download.svg new file mode 100644 index 0000000000000000000000000000000000000000..f0243211ab7be4c7e6ee8b90acc70f08d12672b0 --- /dev/null +++ b/www/assets/css/src/icons/download.svg @@ -0,0 +1,4 @@ +<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="32" height="32" rx="2" fill="#3C4A94"/> +<path d="M7.93333 25.9999C7.4 25.9999 6.94444 25.811 6.56667 25.4333C6.18889 25.0555 6 24.5999 6 24.0666V19.9333H7.5V24.0666C7.5 24.1777 7.54444 24.2777 7.63333 24.3666C7.72222 24.4555 7.82222 24.4999 7.93333 24.4999H24.0667C24.1778 24.4999 24.2778 24.4555 24.3667 24.3666C24.4556 24.2777 24.5 24.1777 24.5 24.0666V19.9333H26V24.0666C26 24.5999 25.8111 25.0555 25.4333 25.4333C25.0556 25.811 24.6 25.9999 24.0667 25.9999H7.93333ZM16 20.9999L10.4667 15.4666L11.5667 14.3999L15.2333 18.0666V5.7666H16.7667V18.0666L20.4333 14.3999L21.5333 15.4666L16 20.9999Z" fill="white"/> +</svg> diff --git a/www/assets/css/src/icons/dropdown.svg b/www/assets/css/src/icons/dropdown.svg new file mode 100644 index 0000000000000000000000000000000000000000..e71599db091853b8eca5d8339b99850ffda0700a --- /dev/null +++ b/www/assets/css/src/icons/dropdown.svg @@ -0,0 +1,3 @@ +<svg width="16" height="10" viewBox="0 0 16 10" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M8.00013 9.56644L0.466797 1.99977L1.53346 0.933105L8.00013 7.39977L14.4668 0.933105L15.5335 2.03311L8.00013 9.56644Z" fill="#5B6186"/> +</svg> diff --git a/www/assets/css/src/icons/fppp-logo.svg b/www/assets/css/src/icons/fppp-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..c546a9c4efa2b3c82e5e93e7f6e225d891abdf0b --- /dev/null +++ b/www/assets/css/src/icons/fppp-logo.svg @@ -0,0 +1,37 @@ +<svg width="195" height="35" viewBox="0 0 195 35" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M39.2445 16V4.05909H47.2668V6.09409H41.5655V9.17182H46.3082V11.0555H41.5655V16H39.2445ZM52.1952 16.1682C51.4888 16.1682 50.8497 16.0505 50.2779 15.815C49.7061 15.5683 49.2184 15.2376 48.8147 14.8227C48.4111 14.4079 48.0972 13.9258 47.8729 13.3764C47.6599 12.827 47.5534 12.2495 47.5534 11.6441C47.5534 11.0162 47.6599 10.4276 47.8729 9.87818C48.086 9.31758 48.3943 8.82985 48.7979 8.415C49.2016 7.98894 49.6893 7.65258 50.2611 7.40591C50.8441 7.15924 51.4944 7.03591 52.212 7.03591C52.9296 7.03591 53.5687 7.15924 54.1293 7.40591C54.7011 7.65258 55.1832 7.98333 55.5757 8.39818C55.9793 8.81303 56.282 9.29515 56.4838 9.84454C56.6969 10.3939 56.8034 10.9658 56.8034 11.56C56.8034 11.7058 56.7978 11.8459 56.7866 11.9805C56.7866 12.115 56.7754 12.2271 56.7529 12.3168H49.9416C49.9752 12.6644 50.0593 12.9727 50.1938 13.2418C50.3284 13.5109 50.5022 13.7408 50.7152 13.9314C50.9282 14.122 51.1693 14.2677 51.4384 14.3686C51.7075 14.4695 51.9878 14.52 52.2793 14.52C52.7278 14.52 53.1482 14.4135 53.5407 14.2005C53.9443 13.9762 54.219 13.6847 54.3647 13.3259L56.2988 13.8641C55.9737 14.5368 55.4523 15.0918 54.7347 15.5291C54.0284 15.9552 53.1819 16.1682 52.1952 16.1682ZM54.4825 10.8536C54.4264 10.1921 54.1797 9.66515 53.7425 9.27273C53.3164 8.86909 52.7951 8.66727 52.1784 8.66727C51.8757 8.66727 51.5897 8.72333 51.3207 8.83545C51.0628 8.93636 50.8329 9.08212 50.6311 9.27273C50.4293 9.46333 50.2611 9.69318 50.1266 9.96227C50.0032 10.2314 49.9304 10.5285 49.9079 10.8536H54.4825ZM64.5504 16V14.6209C64.2589 15.1142 63.8833 15.4955 63.4236 15.7645C62.9639 16.0336 62.4313 16.1682 61.8258 16.1682C61.2204 16.1682 60.6598 16.0505 60.144 15.815C59.6283 15.5795 59.1854 15.2544 58.8154 14.8395C58.4454 14.4247 58.1539 13.9426 57.9408 13.3932C57.739 12.8326 57.6381 12.2327 57.6381 11.5936C57.6381 10.9545 57.7334 10.3603 57.924 9.81091C58.1258 9.26151 58.4005 8.77939 58.7481 8.36454C59.0957 7.9497 59.5105 7.62454 59.9927 7.38909C60.4748 7.15364 60.9961 7.03591 61.5568 7.03591C62.2183 7.03591 62.8069 7.19288 63.3227 7.50682C63.8384 7.82076 64.2477 8.23 64.5504 8.73455V3.72273H66.804V16H64.5504ZM64.5504 10.6686C64.3598 10.1641 64.0458 9.75485 63.6086 9.44091C63.1825 9.11576 62.734 8.95318 62.2631 8.95318C61.9268 8.95318 61.6184 9.03167 61.3381 9.18864C61.0578 9.33439 60.8168 9.53061 60.6149 9.77727C60.4131 10.0239 60.2561 10.3098 60.144 10.635C60.0319 10.9602 59.9758 11.2965 59.9758 11.6441C59.9758 12.0141 60.0375 12.3561 60.1608 12.67C60.2842 12.9839 60.4524 13.2586 60.6654 13.4941C60.8896 13.7295 61.1475 13.9145 61.439 14.0491C61.7305 14.1836 62.0501 14.2509 62.3977 14.2509C62.6219 14.2509 62.8461 14.2173 63.0704 14.15C63.2946 14.0715 63.5021 13.965 63.6927 13.8305C63.8945 13.6959 64.0683 13.5389 64.214 13.3595C64.371 13.1802 64.4831 12.9839 64.5504 12.7709V10.6686ZM72.9223 16.1682C72.2159 16.1682 71.5768 16.0505 71.005 15.815C70.4332 15.5683 69.9455 15.2376 69.5418 14.8227C69.1382 14.4079 68.8243 13.9258 68.6 13.3764C68.387 12.827 68.2805 12.2495 68.2805 11.6441C68.2805 11.0162 68.387 10.4276 68.6 9.87818C68.8131 9.31758 69.1214 8.82985 69.525 8.415C69.9287 7.98894 70.4164 7.65258 70.9882 7.40591C71.5712 7.15924 72.2215 7.03591 72.9391 7.03591C73.6567 7.03591 74.2958 7.15924 74.8564 7.40591C75.4282 7.65258 75.9103 7.98333 76.3028 8.39818C76.7064 8.81303 77.0091 9.29515 77.2109 9.84454C77.424 10.3939 77.5305 10.9658 77.5305 11.56C77.5305 11.7058 77.5249 11.8459 77.5137 11.9805C77.5137 12.115 77.5024 12.2271 77.48 12.3168H70.6687C70.7023 12.6644 70.7864 12.9727 70.9209 13.2418C71.0555 13.5109 71.2293 13.7408 71.4423 13.9314C71.6553 14.122 71.8964 14.2677 72.1655 14.3686C72.4346 14.4695 72.7149 14.52 73.0064 14.52C73.4549 14.52 73.8753 14.4135 74.2678 14.2005C74.6714 13.9762 74.9461 13.6847 75.0918 13.3259L77.0259 13.8641C76.7008 14.5368 76.1794 15.0918 75.4618 15.5291C74.7555 15.9552 73.909 16.1682 72.9223 16.1682ZM75.2096 10.8536C75.1535 10.1921 74.9068 9.66515 74.4696 9.27273C74.0435 8.86909 73.5221 8.66727 72.9055 8.66727C72.6028 8.66727 72.3168 8.72333 72.0478 8.83545C71.7899 8.93636 71.56 9.08212 71.3582 9.27273C71.1564 9.46333 70.9882 9.69318 70.8537 9.96227C70.7303 10.2314 70.6574 10.5285 70.635 10.8536H75.2096ZM84.1507 9.13818C83.4667 9.14939 82.8557 9.28394 82.3175 9.54182C81.7793 9.78848 81.3925 10.1641 81.157 10.6686V16H78.9034V7.18727H80.972V9.07091C81.129 8.76818 81.314 8.49909 81.527 8.26364C81.7401 8.01697 81.9699 7.80394 82.2166 7.62454C82.4632 7.44515 82.7099 7.31061 82.9566 7.22091C83.2145 7.12 83.4611 7.06955 83.6966 7.06955C83.8199 7.06955 83.9096 7.06955 83.9657 7.06955C84.0329 7.06955 84.0946 7.07515 84.1507 7.08636V9.13818ZM90.6742 16V14.7723C90.3378 15.2432 89.9117 15.5964 89.396 15.8318C88.8802 16.0561 88.314 16.1682 87.6973 16.1682C87.2713 16.1682 86.8732 16.1009 86.5032 15.9664C86.1332 15.8206 85.8137 15.6244 85.5446 15.3777C85.2755 15.1198 85.0625 14.8227 84.9055 14.4864C84.7598 14.15 84.6869 13.78 84.6869 13.3764C84.6869 12.9279 84.7878 12.5298 84.9896 12.1823C85.1914 11.8235 85.4661 11.5208 85.8137 11.2741C86.1613 11.0274 86.5593 10.8424 87.0078 10.7191C87.4563 10.5958 87.9328 10.5341 88.4373 10.5341C88.9082 10.5341 89.3287 10.5733 89.6987 10.6518C90.0687 10.7303 90.3658 10.82 90.5901 10.9209V10.4164C90.5901 9.84455 90.4219 9.40167 90.0855 9.08773C89.7604 8.76258 89.2726 8.6 88.6223 8.6C88.1514 8.6 87.6917 8.68409 87.2432 8.85227C86.7948 9.02045 86.3351 9.26712 85.8642 9.59227L85.1746 8.16273C85.7128 7.80394 86.2846 7.52924 86.8901 7.33864C87.5067 7.13682 88.157 7.03591 88.841 7.03591C90.1304 7.03591 91.117 7.35545 91.801 7.99455C92.4961 8.62242 92.8437 9.51379 92.8437 10.6686V16H90.6742ZM90.2201 13.78C90.4667 13.5894 90.5901 13.3764 90.5901 13.1409V12.1318C90.3098 12.0197 90.0126 11.9356 89.6987 11.8795C89.3848 11.8235 89.0876 11.7955 88.8073 11.7955C88.5607 11.7955 88.314 11.8235 88.0673 11.8795C87.8319 11.9356 87.6189 12.0253 87.4282 12.1486C87.2489 12.2608 87.1031 12.4065 86.991 12.5859C86.8789 12.7541 86.8228 12.9559 86.8228 13.1914C86.8228 13.5838 86.9685 13.9033 87.2601 14.15C87.5628 14.3967 87.9216 14.52 88.3364 14.52C88.6728 14.52 89.0148 14.4639 89.3623 14.3518C89.7211 14.2285 90.007 14.0379 90.2201 13.78ZM95.4429 16V9.22227H94.1311V7.18727H95.4429V4.32818H97.7638V7.18727H99.7988V9.22227H97.7638V16H95.4429ZM104.867 16.1682C104.161 16.1682 103.522 16.0505 102.95 15.815C102.378 15.5683 101.89 15.2376 101.487 14.8227C101.083 14.4079 100.769 13.9258 100.545 13.3764C100.332 12.827 100.225 12.2495 100.225 11.6441C100.225 11.0162 100.332 10.4276 100.545 9.87818C100.758 9.31758 101.066 8.82985 101.47 8.415C101.873 7.98894 102.361 7.65258 102.933 7.40591C103.516 7.15924 104.166 7.03591 104.884 7.03591C105.601 7.03591 106.24 7.15924 106.801 7.40591C107.373 7.65258 107.855 7.98333 108.247 8.39818C108.651 8.81303 108.954 9.29515 109.156 9.84454C109.369 10.3939 109.475 10.9658 109.475 11.56C109.475 11.7058 109.47 11.8459 109.458 11.9805C109.458 12.115 109.447 12.2271 109.425 12.3168H102.613C102.647 12.6644 102.731 12.9727 102.866 13.2418C103 13.5109 103.174 13.7408 103.387 13.9314C103.6 14.122 103.841 14.2677 104.11 14.3686C104.379 14.4695 104.66 14.52 104.951 14.52C105.4 14.52 105.82 14.4135 106.212 14.2005C106.616 13.9762 106.891 13.6847 107.037 13.3259L108.971 13.8641C108.645 14.5368 108.124 15.0918 107.407 15.5291C106.7 15.9552 105.854 16.1682 104.867 16.1682ZM107.154 10.8536C107.098 10.1921 106.852 9.66515 106.414 9.27273C105.988 8.86909 105.467 8.66727 104.85 8.66727C104.547 8.66727 104.262 8.72333 103.992 8.83545C103.735 8.93636 103.505 9.08212 103.303 9.27273C103.101 9.46333 102.933 9.69318 102.798 9.96227C102.675 10.2314 102.602 10.5285 102.58 10.8536H107.154ZM117.222 16V14.6209C116.931 15.1142 116.555 15.4955 116.095 15.7645C115.636 16.0336 115.103 16.1682 114.498 16.1682C113.892 16.1682 113.332 16.0505 112.816 15.815C112.3 15.5795 111.857 15.2544 111.487 14.8395C111.117 14.4247 110.826 13.9426 110.613 13.3932C110.411 12.8326 110.31 12.2327 110.31 11.5936C110.31 10.9545 110.405 10.3603 110.596 9.81091C110.798 9.26151 111.072 8.77939 111.42 8.36454C111.767 7.9497 112.182 7.62454 112.664 7.38909C113.147 7.15364 113.668 7.03591 114.229 7.03591C114.89 7.03591 115.479 7.19288 115.994 7.50682C116.51 7.82076 116.919 8.23 117.222 8.73455V3.72273H119.476V16H117.222ZM117.222 10.6686C117.032 10.1641 116.718 9.75485 116.28 9.44091C115.854 9.11576 115.406 8.95318 114.935 8.95318C114.599 8.95318 114.29 9.03167 114.01 9.18864C113.73 9.33439 113.489 9.53061 113.287 9.77727C113.085 10.0239 112.928 10.3098 112.816 10.635C112.704 10.9602 112.648 11.2965 112.648 11.6441C112.648 12.0141 112.709 12.3561 112.833 12.67C112.956 12.9839 113.124 13.2586 113.337 13.4941C113.561 13.7295 113.819 13.9145 114.111 14.0491C114.402 14.1836 114.722 14.2509 115.069 14.2509C115.294 14.2509 115.518 14.2173 115.742 14.15C115.966 14.0715 116.174 13.965 116.364 13.8305C116.566 13.6959 116.74 13.5389 116.886 13.3595C117.043 13.1802 117.155 12.9839 117.222 12.7709V10.6686ZM125.766 16V4.05909H130.828C131.378 4.05909 131.882 4.17682 132.342 4.41227C132.813 4.63651 133.217 4.93924 133.553 5.32045C133.889 5.69045 134.153 6.11651 134.343 6.59864C134.534 7.06955 134.629 7.54606 134.629 8.02818C134.629 8.53273 134.54 9.02606 134.36 9.50818C134.181 9.97909 133.929 10.3995 133.603 10.7695C133.278 11.1395 132.886 11.4367 132.426 11.6609C131.967 11.8852 131.462 11.9973 130.913 11.9973H128.087V16H125.766ZM128.087 9.96227H130.778C131.204 9.96227 131.557 9.78848 131.838 9.44091C132.129 9.09333 132.275 8.62242 132.275 8.02818C132.275 7.72545 132.23 7.45636 132.14 7.22091C132.051 6.97424 131.933 6.76682 131.787 6.59864C131.641 6.43045 131.468 6.30712 131.266 6.22864C131.075 6.13894 130.879 6.09409 130.677 6.09409H128.087V9.96227ZM139.965 16.1682C139.259 16.1682 138.62 16.0505 138.048 15.815C137.476 15.5683 136.988 15.2376 136.585 14.8227C136.181 14.4079 135.867 13.9258 135.643 13.3764C135.43 12.827 135.323 12.2495 135.323 11.6441C135.323 11.0162 135.43 10.4276 135.643 9.87818C135.856 9.31758 136.164 8.82985 136.568 8.415C136.971 7.98894 137.459 7.65258 138.031 7.40591C138.614 7.15924 139.264 7.03591 139.982 7.03591C140.699 7.03591 141.339 7.15924 141.899 7.40591C142.471 7.65258 142.953 7.98333 143.346 8.39818C143.749 8.81303 144.052 9.29515 144.254 9.84454C144.467 10.3939 144.573 10.9658 144.573 11.56C144.573 11.7058 144.568 11.8459 144.556 11.9805C144.556 12.115 144.545 12.2271 144.523 12.3168H137.711C137.745 12.6644 137.829 12.9727 137.964 13.2418C138.098 13.5109 138.272 13.7408 138.485 13.9314C138.698 14.122 138.939 14.2677 139.208 14.3686C139.477 14.4695 139.758 14.52 140.049 14.52C140.498 14.52 140.918 14.4135 141.311 14.2005C141.714 13.9762 141.989 13.6847 142.135 13.3259L144.069 13.8641C143.744 14.5368 143.222 15.0918 142.505 15.5291C141.798 15.9552 140.952 16.1682 139.965 16.1682ZM142.252 10.8536C142.196 10.1921 141.95 9.66515 141.512 9.27273C141.086 8.86909 140.565 8.66727 139.948 8.66727C139.646 8.66727 139.36 8.72333 139.091 8.83545C138.833 8.93636 138.603 9.08212 138.401 9.27273C138.199 9.46333 138.031 9.69318 137.896 9.96227C137.773 10.2314 137.7 10.5285 137.678 10.8536H142.252ZM151.193 9.13818C150.51 9.14939 149.898 9.28394 149.36 9.54182C148.822 9.78848 148.435 10.1641 148.2 10.6686V16H145.946V7.18727H148.015V9.07091C148.172 8.76818 148.357 8.49909 148.57 8.26364C148.783 8.01697 149.013 7.80394 149.259 7.62454C149.506 7.44515 149.753 7.31061 149.999 7.22091C150.257 7.12 150.504 7.06955 150.739 7.06955C150.863 7.06955 150.952 7.06955 151.008 7.06955C151.076 7.06955 151.137 7.07515 151.193 7.08636V9.13818ZM155.78 16.1682C155.04 16.1682 154.317 16.0505 153.611 15.815C152.904 15.5795 152.299 15.2432 151.794 14.8059L152.635 13.3932C153.173 13.7744 153.695 14.0659 154.199 14.2677C154.715 14.4583 155.225 14.5536 155.73 14.5536C156.178 14.5536 156.531 14.4695 156.789 14.3014C157.047 14.1332 157.176 13.8921 157.176 13.5782C157.176 13.2642 157.025 13.0344 156.722 12.8886C156.419 12.7429 155.926 12.5747 155.242 12.3841C154.67 12.2271 154.182 12.0758 153.779 11.93C153.375 11.7842 153.05 11.6217 152.803 11.4423C152.557 11.2517 152.377 11.0386 152.265 10.8032C152.153 10.5565 152.097 10.265 152.097 9.92864C152.097 9.48015 152.181 9.07651 152.349 8.71773C152.529 8.35894 152.775 8.05621 153.089 7.80955C153.403 7.55167 153.768 7.35545 154.182 7.22091C154.608 7.08636 155.068 7.01909 155.561 7.01909C156.223 7.01909 156.84 7.11439 157.411 7.305C157.994 7.49561 158.527 7.80394 159.009 8.23L158.101 9.59227C157.653 9.25591 157.215 9.00924 156.789 8.85227C156.374 8.6953 155.959 8.61682 155.545 8.61682C155.163 8.61682 154.844 8.6953 154.586 8.85227C154.328 9.00924 154.199 9.26151 154.199 9.60909C154.199 9.76606 154.227 9.895 154.283 9.99591C154.351 10.0968 154.451 10.1865 154.586 10.265C154.721 10.3435 154.894 10.422 155.107 10.5005C155.332 10.5677 155.606 10.6406 155.931 10.7191C156.537 10.8761 157.053 11.033 157.479 11.19C157.916 11.347 158.269 11.5264 158.538 11.7282C158.819 11.93 159.02 12.1655 159.144 12.4345C159.278 12.6924 159.346 13.0064 159.346 13.3764C159.346 14.2397 159.026 14.9236 158.387 15.4282C157.748 15.9215 156.879 16.1682 155.78 16.1682ZM164.88 16.1682C164.162 16.1682 163.518 16.0448 162.946 15.7982C162.374 15.5515 161.886 15.2208 161.483 14.8059C161.09 14.3798 160.787 13.8921 160.574 13.3427C160.361 12.7933 160.255 12.2159 160.255 11.6105C160.255 10.9938 160.361 10.4108 160.574 9.86136C160.787 9.31197 161.09 8.82985 161.483 8.415C161.886 7.98894 162.374 7.65258 162.946 7.40591C163.518 7.15924 164.162 7.03591 164.88 7.03591C165.597 7.03591 166.237 7.15924 166.797 7.40591C167.369 7.65258 167.851 7.98894 168.244 8.415C168.647 8.82985 168.956 9.31197 169.169 9.86136C169.382 10.4108 169.488 10.9938 169.488 11.6105C169.488 12.2159 169.382 12.7933 169.169 13.3427C168.956 13.8921 168.653 14.3798 168.26 14.8059C167.868 15.2208 167.386 15.5515 166.814 15.7982C166.242 16.0448 165.597 16.1682 164.88 16.1682ZM162.576 11.6105C162.576 12.0029 162.632 12.3617 162.744 12.6868C162.867 13.0008 163.03 13.2755 163.232 13.5109C163.445 13.7464 163.691 13.9314 163.972 14.0659C164.252 14.1892 164.555 14.2509 164.88 14.2509C165.205 14.2509 165.508 14.1892 165.788 14.0659C166.068 13.9314 166.309 13.7464 166.511 13.5109C166.724 13.2755 166.887 12.9952 166.999 12.67C167.122 12.3448 167.184 11.9861 167.184 11.5936C167.184 11.2124 167.122 10.8592 166.999 10.5341C166.887 10.2089 166.724 9.92864 166.511 9.69318C166.309 9.45773 166.068 9.27833 165.788 9.155C165.508 9.02045 165.205 8.95318 164.88 8.95318C164.555 8.95318 164.252 9.02045 163.972 9.155C163.691 9.28955 163.445 9.47455 163.232 9.71C163.03 9.94545 162.867 10.2258 162.744 10.5509C162.632 10.8761 162.576 11.2292 162.576 11.6105ZM179.2 16H176.946V11.0555C176.946 10.3491 176.823 9.83333 176.576 9.50818C176.329 9.18303 175.987 9.02045 175.55 9.02045C175.326 9.02045 175.096 9.0653 174.861 9.155C174.625 9.2447 174.401 9.37364 174.188 9.54182C173.986 9.69879 173.801 9.88939 173.633 10.1136C173.465 10.3379 173.341 10.5845 173.263 10.8536V16H171.009V7.18727H173.044V8.81864C173.369 8.25803 173.84 7.82076 174.457 7.50682C175.074 7.19288 175.769 7.03591 176.542 7.03591C177.092 7.03591 177.54 7.13682 177.888 7.33864C178.235 7.54045 178.505 7.80394 178.695 8.12909C178.886 8.45424 179.015 8.82424 179.082 9.23909C179.16 9.65394 179.2 10.0744 179.2 10.5005V16ZM186.541 16V14.7723C186.205 15.2432 185.779 15.5964 185.263 15.8318C184.747 16.0561 184.181 16.1682 183.564 16.1682C183.138 16.1682 182.74 16.1009 182.37 15.9664C182 15.8206 181.681 15.6244 181.412 15.3777C181.142 15.1198 180.929 14.8227 180.772 14.4864C180.627 14.15 180.554 13.78 180.554 13.3764C180.554 12.9279 180.655 12.5298 180.857 12.1823C181.058 11.8235 181.333 11.5208 181.681 11.2741C182.028 11.0274 182.426 10.8424 182.875 10.7191C183.323 10.5958 183.8 10.5341 184.304 10.5341C184.775 10.5341 185.196 10.5733 185.566 10.6518C185.936 10.7303 186.233 10.82 186.457 10.9209V10.4164C186.457 9.84455 186.289 9.40167 185.952 9.08773C185.627 8.76258 185.14 8.6 184.489 8.6C184.018 8.6 183.559 8.68409 183.11 8.85227C182.662 9.02045 182.202 9.26712 181.731 9.59227L181.042 8.16273C181.58 7.80394 182.152 7.52924 182.757 7.33864C183.374 7.13682 184.024 7.03591 184.708 7.03591C185.997 7.03591 186.984 7.35545 187.668 7.99455C188.363 8.62242 188.711 9.51379 188.711 10.6686V16H186.541ZM186.087 13.78C186.334 13.5894 186.457 13.3764 186.457 13.1409V12.1318C186.177 12.0197 185.88 11.9356 185.566 11.8795C185.252 11.8235 184.955 11.7955 184.674 11.7955C184.428 11.7955 184.181 11.8235 183.934 11.8795C183.699 11.9356 183.486 12.0253 183.295 12.1486C183.116 12.2608 182.97 12.4065 182.858 12.5859C182.746 12.7541 182.69 12.9559 182.69 13.1914C182.69 13.5838 182.835 13.9033 183.127 14.15C183.43 14.3967 183.788 14.52 184.203 14.52C184.54 14.52 184.882 14.4639 185.229 14.3518C185.588 14.2285 185.874 14.0379 186.087 13.78ZM190.702 3.72273H192.956V16H190.702V3.72273Z" fill="#4859B2"/> +<path d="M39.281 31.5044V20.8041H43.742C44.2142 20.8041 44.6462 20.9046 45.0381 21.1055C45.44 21.2964 45.7816 21.5576 46.0629 21.8892C46.3543 22.2107 46.5803 22.5774 46.7411 22.9894C46.9018 23.3913 46.9822 23.8032 46.9822 24.2252C46.9822 24.6673 46.9069 25.0943 46.7562 25.5062C46.6054 25.9181 46.3894 26.2849 46.1081 26.6064C45.8368 26.9279 45.5053 27.1841 45.1134 27.375C44.7316 27.5659 44.3046 27.6613 43.8324 27.6613H40.6374V31.5044H39.281ZM40.6374 26.4557H43.7571C44.0384 26.4557 44.2896 26.4004 44.5106 26.2899C44.7417 26.1693 44.9376 26.0086 45.0984 25.8076C45.2591 25.5966 45.3847 25.3555 45.4751 25.0842C45.5656 24.8129 45.6108 24.5266 45.6108 24.2252C45.6108 23.9137 45.5555 23.6223 45.445 23.3511C45.3445 23.0798 45.2039 22.8437 45.023 22.6427C44.8522 22.4418 44.6462 22.2861 44.4051 22.1755C44.174 22.065 43.9279 22.0098 43.6666 22.0098H40.6374V26.4557ZM52.6194 24.7979C51.9563 24.818 51.3685 24.9888 50.8561 25.3103C50.3538 25.6318 49.9971 26.0789 49.7861 26.6516V31.5044H48.4599V23.6374H49.6957V25.461C49.967 24.9184 50.3236 24.4814 50.7657 24.1498C51.2078 23.8082 51.68 23.6173 52.1824 23.5771C52.2828 23.5771 52.3682 23.5771 52.4386 23.5771C52.5089 23.5771 52.5692 23.5822 52.6194 23.5922V24.7979ZM57.1944 31.6551C56.6016 31.6551 56.059 31.5446 55.5667 31.3235C55.0844 31.1025 54.6675 30.8061 54.3158 30.4344C53.9742 30.0626 53.708 29.6306 53.5171 29.1383C53.3262 28.646 53.2307 28.1285 53.2307 27.586C53.2307 27.0334 53.3262 26.5109 53.5171 26.0186C53.718 25.5263 53.9893 25.0943 54.3309 24.7225C54.6826 24.3508 55.0995 24.0544 55.5818 23.8333C56.0741 23.6123 56.6116 23.5018 57.1944 23.5018C57.7771 23.5018 58.3146 23.6123 58.8069 23.8333C59.2993 24.0544 59.7162 24.3508 60.0578 24.7225C60.4095 25.0943 60.6807 25.5263 60.8716 26.0186C61.0726 26.5109 61.1731 27.0334 61.1731 27.586C61.1731 28.1285 61.0776 28.646 60.8867 29.1383C60.6958 29.6306 60.4245 30.0626 60.0729 30.4344C59.7212 30.8061 59.2993 31.1025 58.8069 31.3235C58.3247 31.5446 57.7871 31.6551 57.1944 31.6551ZM54.5871 27.601C54.5871 28.013 54.6524 28.3948 54.783 28.7464C54.9237 29.0981 55.1096 29.4045 55.3406 29.6658C55.5818 29.927 55.8581 30.1329 56.1695 30.2837C56.4911 30.4344 56.8327 30.5097 57.1944 30.5097C57.5561 30.5097 57.8926 30.4344 58.2041 30.2837C58.5256 30.1329 58.8069 29.927 59.0481 29.6658C59.2892 29.3945 59.4751 29.083 59.6057 28.7314C59.7464 28.3697 59.8167 27.9828 59.8167 27.5709C59.8167 27.169 59.7464 26.7922 59.6057 26.4406C59.4751 26.0789 59.2892 25.7674 59.0481 25.5062C58.8069 25.2349 58.5256 25.0239 58.2041 24.8732C57.8926 24.7225 57.5561 24.6472 57.1944 24.6472C56.8327 24.6472 56.4911 24.7275 56.1695 24.8883C55.8581 25.039 55.5818 25.25 55.3406 25.5213C55.1096 25.7825 54.9237 26.094 54.783 26.4557C54.6524 26.8073 54.5871 27.1891 54.5871 27.601ZM63.0696 31.5044V24.6773H61.9996V23.6374H63.0696V23.4716C63.0696 22.4971 63.2856 21.7335 63.7177 21.1809C64.1497 20.6283 64.7375 20.352 65.481 20.352C65.7924 20.352 66.0989 20.3972 66.4003 20.4876C66.7017 20.568 66.973 20.6835 67.2141 20.8342L66.8826 21.8138C66.7419 21.7134 66.5661 21.633 66.3551 21.5727C66.1541 21.5124 65.9532 21.4823 65.7522 21.4823C65.3102 21.4823 64.9736 21.6481 64.7425 21.9796C64.5114 22.3112 64.3959 22.7934 64.3959 23.4264V23.6374H66.4907V24.6773H64.3959V31.5044H63.0696ZM67.8135 31.5044V23.6374H69.1398V31.5044H67.8135ZM67.8135 22.1605V20.5027H69.1398V22.1605H67.8135ZM71.3622 20.5027H72.6885V31.5044H71.3622V20.5027ZM78.3888 31.6551C77.796 31.6551 77.2534 31.5496 76.7611 31.3386C76.2688 31.1176 75.8468 30.8212 75.4952 30.4494C75.1435 30.0777 74.8672 29.6457 74.6663 29.1533C74.4754 28.651 74.3799 28.1235 74.3799 27.5709C74.3799 27.0183 74.4754 26.4959 74.6663 26.0035C74.8672 25.5112 75.1435 25.0792 75.4952 24.7074C75.8569 24.3357 76.2839 24.0443 76.7762 23.8333C77.2685 23.6123 77.8111 23.5018 78.4039 23.5018C78.9966 23.5018 79.5342 23.6123 80.0164 23.8333C80.5087 24.0544 80.9257 24.3508 81.2673 24.7225C81.6089 25.0842 81.8701 25.5112 82.051 26.0035C82.2419 26.4858 82.3373 26.9882 82.3373 27.5106C82.3373 27.6211 82.3323 27.7216 82.3223 27.812C82.3223 27.9025 82.3172 27.9728 82.3072 28.023H75.7815C75.8117 28.4149 75.9021 28.7715 76.0528 29.0931C76.2035 29.4146 76.3994 29.6909 76.6406 29.922C76.8817 30.153 77.153 30.3339 77.4544 30.4645C77.7659 30.5951 78.0924 30.6604 78.434 30.6604C78.6751 30.6604 78.9112 30.6303 79.1423 30.57C79.3734 30.4997 79.5894 30.4092 79.7904 30.2987C79.9913 30.1882 80.1671 30.0526 80.3179 29.8918C80.4786 29.7311 80.5992 29.5502 80.6796 29.3493L81.8249 29.6658C81.6943 29.9571 81.5135 30.2234 81.2824 30.4645C81.0613 30.7056 80.8001 30.9166 80.4987 31.0975C80.2073 31.2683 79.8808 31.4039 79.5191 31.5044C79.1574 31.6049 78.7806 31.6551 78.3888 31.6551ZM81.0865 27.0434C81.0563 26.6717 80.9609 26.3301 80.8001 26.0186C80.6494 25.6971 80.4535 25.4258 80.2124 25.2048C79.9813 24.9837 79.71 24.8129 79.3985 24.6924C79.0871 24.5618 78.7555 24.4965 78.4039 24.4965C78.0522 24.4965 77.7206 24.5618 77.4092 24.6924C77.0977 24.8129 76.8214 24.9888 76.5803 25.2199C76.3492 25.4409 76.1583 25.7071 76.0076 26.0186C75.8669 26.3301 75.7815 26.6717 75.7514 27.0434H81.0865ZM87.8344 31.5044V20.8041H92.2954C92.7676 20.8041 93.1997 20.9046 93.5915 21.1055C93.9934 21.2964 94.335 21.5576 94.6163 21.8892C94.9077 22.2107 95.1337 22.5774 95.2945 22.9894C95.4553 23.3913 95.5356 23.8032 95.5356 24.2252C95.5356 24.6673 95.4603 25.0943 95.3096 25.5062C95.1589 25.9181 94.9428 26.2849 94.6615 26.6064C94.3902 26.9279 94.0587 27.1841 93.6668 27.375C93.2851 27.5659 92.858 27.6613 92.3858 27.6613H89.1908V31.5044H87.8344ZM89.1908 26.4557H92.3105C92.5918 26.4557 92.843 26.4004 93.064 26.2899C93.2951 26.1693 93.491 26.0086 93.6518 25.8076C93.8125 25.5966 93.9381 25.3555 94.0285 25.0842C94.119 24.8129 94.1642 24.5266 94.1642 24.2252C94.1642 23.9137 94.1089 23.6223 93.9984 23.3511C93.8979 23.0798 93.7573 22.8437 93.5764 22.6427C93.4056 22.4418 93.1997 22.2861 92.9585 22.1755C92.7274 22.065 92.4813 22.0098 92.22 22.0098H89.1908V26.4557ZM101.868 31.5044V30.3138C101.527 30.776 101.095 31.1176 100.572 31.3386C100.06 31.5496 99.5172 31.6551 98.9445 31.6551C98.5727 31.6551 98.2261 31.5948 97.9046 31.4743C97.5831 31.3436 97.3017 31.1678 97.0606 30.9468C96.8295 30.7257 96.6437 30.4695 96.503 30.1782C96.3724 29.8767 96.3071 29.5502 96.3071 29.1986C96.3071 28.7866 96.4025 28.4299 96.5934 28.1285C96.7843 27.8171 97.0355 27.5609 97.347 27.3599C97.6685 27.159 98.0251 27.0133 98.417 26.9229C98.8088 26.8224 99.2107 26.7722 99.6227 26.7722C100.135 26.7722 100.577 26.8174 100.949 26.9078C101.331 26.9882 101.622 27.0736 101.823 27.164V26.531C101.823 25.898 101.642 25.3957 101.28 25.0239C100.919 24.6522 100.406 24.4663 99.7432 24.4663C98.9495 24.4663 98.1156 24.7728 97.2415 25.3856L96.8044 24.5266C97.2565 24.2252 97.7338 23.979 98.2361 23.7881C98.7485 23.5972 99.2911 23.5018 99.8638 23.5018C100.396 23.5018 100.863 23.5771 101.265 23.7278C101.677 23.8785 102.024 24.0946 102.305 24.3759C102.587 24.6472 102.798 24.9787 102.938 25.3706C103.079 25.7624 103.149 26.1944 103.149 26.6667V31.5044H101.868ZM101.537 29.6959C101.728 29.4849 101.823 29.289 101.823 29.1081V27.9477C101.501 27.8171 101.165 27.7216 100.813 27.6613C100.472 27.601 100.14 27.5709 99.8186 27.5709C99.5573 27.5709 99.2911 27.601 99.0198 27.6613C98.7586 27.7116 98.5175 27.802 98.2964 27.9326C98.0854 28.0532 97.9096 28.2089 97.7689 28.3998C97.6383 28.5907 97.573 28.8218 97.573 29.0931C97.573 29.3241 97.6182 29.5402 97.7087 29.7411C97.7991 29.932 97.9247 30.0978 98.0854 30.2384C98.2462 30.3691 98.427 30.4746 98.628 30.5549C98.839 30.6253 99.06 30.6604 99.2911 30.6604C99.492 30.6604 99.698 30.6403 99.909 30.6001C100.13 30.56 100.341 30.5047 100.542 30.4344C100.743 30.354 100.929 30.2535 101.1 30.1329C101.27 30.0124 101.416 29.8667 101.537 29.6959ZM108.331 31.5948C107.799 31.5948 107.306 31.4843 106.854 31.2633C106.412 31.0422 106.03 30.7458 105.709 30.3741C105.387 30.0023 105.136 29.5753 104.955 29.0931C104.784 28.6108 104.699 28.1084 104.699 27.586C104.699 27.0334 104.784 26.5109 104.955 26.0186C105.136 25.5162 105.387 25.0792 105.709 24.7074C106.03 24.3357 106.412 24.0443 106.854 23.8333C107.306 23.6123 107.804 23.5018 108.346 23.5018C109.009 23.5018 109.582 23.6625 110.064 23.984C110.546 24.3056 110.953 24.7125 111.285 25.2048V23.6374H112.46V31.414C112.46 31.9766 112.355 32.4689 112.144 32.8909C111.933 33.3229 111.647 33.6846 111.285 33.976C110.923 34.2674 110.496 34.4884 110.004 34.6391C109.522 34.7898 109.004 34.8652 108.452 34.8652C107.557 34.8652 106.829 34.7095 106.266 34.398C105.714 34.0966 105.252 33.6746 104.88 33.132L105.648 32.4539C105.96 32.916 106.362 33.2627 106.854 33.4937C107.346 33.7248 107.879 33.8404 108.452 33.8404C108.813 33.8404 109.155 33.7901 109.476 33.6897C109.808 33.5892 110.094 33.4385 110.335 33.2375C110.577 33.0366 110.767 32.7854 110.908 32.484C111.059 32.1826 111.134 31.8259 111.134 31.414V30.0275C110.983 30.2686 110.803 30.4896 110.592 30.6906C110.391 30.8815 110.17 31.0472 109.929 31.1879C109.687 31.3185 109.431 31.419 109.16 31.4893C108.889 31.5597 108.612 31.5948 108.331 31.5948ZM108.738 30.5097C109.019 30.5097 109.291 30.4595 109.552 30.359C109.813 30.2585 110.054 30.1279 110.275 29.9672C110.496 29.7964 110.682 29.6055 110.833 29.3945C110.983 29.1835 111.084 28.9675 111.134 28.7464V26.4858C111.024 26.2145 110.878 25.9684 110.697 25.7473C110.526 25.5263 110.33 25.3354 110.109 25.1746C109.888 25.0038 109.647 24.8732 109.386 24.7828C109.135 24.6924 108.879 24.6472 108.617 24.6472C108.215 24.6472 107.854 24.7326 107.532 24.9034C107.221 25.0742 106.955 25.3002 106.733 25.5816C106.512 25.8629 106.342 26.1844 106.221 26.5461C106.101 26.8977 106.04 27.2544 106.04 27.6161C106.04 28.008 106.111 28.3797 106.251 28.7314C106.392 29.083 106.583 29.3895 106.824 29.6507C107.065 29.9119 107.346 30.1229 107.668 30.2837C107.999 30.4344 108.356 30.5097 108.738 30.5097ZM118.082 31.6551C117.489 31.6551 116.947 31.5496 116.455 31.3386C115.962 31.1176 115.54 30.8212 115.189 30.4494C114.837 30.0777 114.561 29.6457 114.36 29.1533C114.169 28.651 114.073 28.1235 114.073 27.5709C114.073 27.0183 114.169 26.4959 114.36 26.0035C114.561 25.5112 114.837 25.0792 115.189 24.7074C115.55 24.3357 115.977 24.0443 116.47 23.8333C116.962 23.6123 117.504 23.5018 118.097 23.5018C118.69 23.5018 119.228 23.6123 119.71 23.8333C120.202 24.0544 120.619 24.3508 120.961 24.7225C121.302 25.0842 121.564 25.5112 121.744 26.0035C121.935 26.4858 122.031 26.9882 122.031 27.5106C122.031 27.6211 122.026 27.7216 122.016 27.812C122.016 27.9025 122.011 27.9728 122.001 28.023H115.475C115.505 28.4149 115.596 28.7715 115.746 29.0931C115.897 29.4146 116.093 29.6909 116.334 29.922C116.575 30.153 116.846 30.3339 117.148 30.4645C117.459 30.5951 117.786 30.6604 118.127 30.6604C118.369 30.6604 118.605 30.6303 118.836 30.57C119.067 30.4997 119.283 30.4092 119.484 30.2987C119.685 30.1882 119.861 30.0526 120.011 29.8918C120.172 29.7311 120.293 29.5502 120.373 29.3493L121.518 29.6658C121.388 29.9571 121.207 30.2234 120.976 30.4645C120.755 30.7056 120.494 30.9166 120.192 31.0975C119.901 31.2683 119.574 31.4039 119.213 31.5044C118.851 31.6049 118.474 31.6551 118.082 31.6551ZM120.78 27.0434C120.75 26.6717 120.654 26.3301 120.494 26.0186C120.343 25.6971 120.147 25.4258 119.906 25.2048C119.675 24.9837 119.403 24.8129 119.092 24.6924C118.78 24.5618 118.449 24.4965 118.097 24.4965C117.746 24.4965 117.414 24.5618 117.103 24.6924C116.791 24.8129 116.515 24.9888 116.274 25.2199C116.043 25.4409 115.852 25.7071 115.701 26.0186C115.56 26.3301 115.475 26.6717 115.445 27.0434H120.78Z" fill="#4859B2"/> +<mask id="mask0_239_6997" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="1" width="33" height="33"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M16.0537 1.9751H3.27627C1.46684 1.9751 0 3.44193 0 5.25137V17.828V30.4047C0 32.2141 1.46684 33.681 3.27627 33.681H16.0537H28.8312C30.6406 33.681 32.1074 32.2141 32.1074 30.4047V17.828V5.25137C32.1074 3.44193 30.6406 1.9751 28.8312 1.9751H16.0537ZM16.0537 1.9751C24.9199 1.9751 32.1074 9.0727 32.1074 17.828C32.1074 26.5834 24.9199 33.681 16.0537 33.681C7.18749 33.681 0 26.5834 0 17.828C0 9.0727 7.18749 1.9751 16.0537 1.9751Z" fill="#D9D9D9"/> +<path d="M32.1074 17.828C32.1074 26.5834 24.9199 33.681 16.0537 33.681C7.18749 33.681 0 26.5834 0 17.828C0 9.0727 7.18749 1.9751 16.0537 1.9751C24.9199 1.9751 32.1074 9.0727 32.1074 17.828ZM2.29328 17.828C2.29328 25.3327 8.45404 31.4164 16.0537 31.4164C23.6534 31.4164 29.8142 25.3327 29.8142 17.828C29.8142 10.3234 23.6534 4.2397 16.0537 4.2397C8.45404 4.2397 2.29328 10.3234 2.29328 17.828Z" fill="#D9D9D9"/> +<path d="M6.22656 14.916H12.0146C12.0146 14.916 13.4344 16.4258 16.1646 16.5337C18.6764 16.4258 20.0961 14.916 20.0961 14.916H25.8842V27.4258C18.3422 33.8035 13.2159 33.5729 6.22656 27.4258V14.916Z" fill="#D9D9D9" stroke="black" stroke-width="0.218418"/> +<ellipse cx="16.055" cy="10.7104" rx="4.9144" ry="4.85294" fill="#D9D9D9"/> +</mask> +<g mask="url(#mask0_239_6997)"> +<rect y="1.9751" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect x="6.70312" y="1.9751" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect x="13.3242" y="1.9751" width="5.46045" height="3.23529" fill="#EF883B"/> +<rect x="20.1094" y="1.9751" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect x="26.8164" y="1.9751" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect y="8.59521" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect x="6.76953" y="8.66162" width="3.93152" height="5.17647" fill="#EF883B"/> +<rect x="12.2305" y="7.58301" width="7.64463" height="7.54902" rx="3.77451" fill="#4859B2"/> +<rect x="21.625" y="8.66162" width="3.7131" height="5.17647" fill="#EF883B"/> +<rect x="26.8164" y="8.59473" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect y="15.2148" width="5.29244" height="5.22624" fill="#EF883B"/> +<path d="M6.70312 18.4911C6.70312 16.6817 8.16996 15.2148 9.97939 15.2148H11.9956V20.4411H6.70312V18.4911Z" fill="#4859B2"/> +<rect x="13.3242" y="15.5635" width="5.46045" height="4.96078" fill="#4859B2"/> +<path d="M20.1094 15.2148H22.1255C23.935 15.2148 25.4018 16.6817 25.4018 18.4911V20.4411H20.1094V15.2148Z" fill="#4859B2"/> +<rect x="26.8164" y="15.2148" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect y="21.835" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect x="6.70312" y="21.835" width="5.29244" height="5.22624" fill="#4859B2"/> +<rect x="13.4062" y="21.835" width="5.29244" height="5.22624" fill="#4859B2"/> +<rect x="20.1094" y="21.835" width="5.29244" height="5.22624" fill="#4859B2"/> +<rect x="26.8164" y="21.835" width="5.29244" height="5.22624" fill="#EF883B"/> +<rect y="28.4546" width="5.29244" height="5.22624" fill="#4859B2"/> +<rect x="6.70312" y="28.4546" width="5.29244" height="5.22624" fill="#4859B2"/> +<rect x="13.4062" y="28.4546" width="5.29244" height="5.22624" fill="#4859B2"/> +<rect x="20.1094" y="28.4546" width="5.29244" height="5.22624" fill="#4859B2"/> +<rect x="26.8164" y="28.4546" width="5.29244" height="5.22624" fill="#4859B2"/> +</g> +</svg> diff --git a/www/assets/css/src/icons/i.svg b/www/assets/css/src/icons/i.svg new file mode 100644 index 0000000000000000000000000000000000000000..464804df90d6ff1d8f31ec37c7c96279b646ad81 --- /dev/null +++ b/www/assets/css/src/icons/i.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M11.416 17.542H12.7285V10.8337H11.416V17.542ZM11.9993 8.96699C12.2132 8.96699 12.398 8.89407 12.5535 8.74824C12.7091 8.60241 12.7868 8.41283 12.7868 8.17949C12.7868 7.94616 12.7139 7.75658 12.5681 7.61074C12.4223 7.46491 12.2327 7.39199 11.9993 7.39199C11.766 7.39199 11.5764 7.46491 11.4306 7.61074C11.2848 7.75658 11.2118 7.94616 11.2118 8.17949C11.2118 8.41283 11.2848 8.60241 11.4306 8.74824C11.5764 8.89407 11.766 8.96699 11.9993 8.96699ZM11.9993 23.0837C10.4632 23.0837 9.02435 22.792 7.68268 22.2087C6.34102 21.6253 5.16949 20.833 4.1681 19.8316C3.16671 18.8302 2.37435 17.6587 1.79102 16.317C1.20768 14.9753 0.916016 13.5364 0.916016 12.0003C0.916016 10.4642 1.20768 9.02046 1.79102 7.66908C2.37435 6.31769 3.16671 5.14616 4.1681 4.15449C5.16949 3.16283 6.34102 2.37533 7.68268 1.79199C9.02435 1.20866 10.4632 0.916992 11.9993 0.916992C13.5355 0.916992 14.9792 1.20866 16.3306 1.79199C17.682 2.37533 18.8535 3.16283 19.8452 4.15449C20.8368 5.14616 21.6243 6.31769 22.2077 7.66908C22.791 9.02046 23.0827 10.4642 23.0827 12.0003C23.0827 13.5364 22.791 14.9753 22.2077 16.317C21.6243 17.6587 20.8368 18.8302 19.8452 19.8316C18.8535 20.833 17.682 21.6253 16.3306 22.2087C14.9792 22.792 13.5355 23.0837 11.9993 23.0837ZM12.0285 21.7712C14.7313 21.7712 17.0306 20.8184 18.9264 18.9128C20.8223 17.0073 21.7702 14.6934 21.7702 11.9712C21.7702 9.26838 20.8223 6.96908 18.9264 5.07324C17.0306 3.17741 14.7216 2.22949 11.9993 2.22949C9.29657 2.22949 6.9924 3.17741 5.08685 5.07324C3.18129 6.96908 2.22852 9.2781 2.22852 12.0003C2.22852 14.7031 3.18129 17.0073 5.08685 18.9128C6.9924 20.8184 9.30629 21.7712 12.0285 21.7712Z" fill="#4859B2"/> +</svg> diff --git a/www/assets/css/src/icons/logout.svg b/www/assets/css/src/icons/logout.svg new file mode 100644 index 0000000000000000000000000000000000000000..b70c4bb938038d57afa0339eed4571170c64cc76 --- /dev/null +++ b/www/assets/css/src/icons/logout.svg @@ -0,0 +1,3 @@ +<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M1.89089 20.4997C1.42422 20.4997 1.02561 20.3344 0.695052 20.0038C0.364497 19.6733 0.199219 19.2747 0.199219 18.808V1.77467C0.199219 1.30801 0.364497 0.909397 0.695052 0.578841C1.02561 0.248286 1.42422 0.0830078 1.89089 0.0830078H9.94089V1.39551H1.89089C1.79366 1.39551 1.70616 1.4344 1.62839 1.51217C1.55061 1.58995 1.51172 1.67745 1.51172 1.77467V18.808C1.51172 18.9052 1.55061 18.9927 1.62839 19.0705C1.70616 19.1483 1.79366 19.1872 1.89089 19.1872H9.94089V20.4997H1.89089ZM15.3659 14.7247L14.4034 13.7913L17.2617 10.9622H6.96588V9.62051H17.2326L14.3742 6.79134L15.3367 5.82884L19.7992 10.3205L15.3659 14.7247Z" fill="black"/> +</svg> diff --git a/www/assets/css/src/icons/prof-page.svg b/www/assets/css/src/icons/prof-page.svg new file mode 100644 index 0000000000000000000000000000000000000000..c353f4e25b3415dd578582b9c2fb82e95884b4b1 --- /dev/null +++ b/www/assets/css/src/icons/prof-page.svg @@ -0,0 +1,3 @@ +<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M5.39844 21.6705C6.54566 20.6011 7.84358 19.7406 9.29219 19.0893C10.7408 18.4379 12.3109 18.1122 14.0026 18.1122C15.6943 18.1122 17.2644 18.4379 18.713 19.0893C20.1616 19.7406 21.4595 20.6011 22.6068 21.6705V5.77467C22.6068 5.67745 22.5679 5.58995 22.4901 5.51217C22.4123 5.4344 22.3248 5.39551 22.2276 5.39551H5.7776C5.68038 5.39551 5.59288 5.4344 5.5151 5.51217C5.43733 5.58995 5.39844 5.67745 5.39844 5.77467V21.6705ZM14.0318 15.633C15.0818 15.633 15.9714 15.2684 16.7005 14.5393C17.4297 13.8101 17.7943 12.9205 17.7943 11.8705C17.7943 10.8205 17.4297 9.93092 16.7005 9.20176C15.9714 8.47259 15.0818 8.10801 14.0318 8.10801C12.9818 8.10801 12.097 8.47259 11.3776 9.20176C10.6582 9.93092 10.2984 10.8205 10.2984 11.8705C10.2984 12.9205 10.6582 13.8101 11.3776 14.5393C12.097 15.2684 12.9818 15.633 14.0318 15.633ZM5.7776 23.9163C5.31094 23.9163 4.91233 23.7511 4.58177 23.4205C4.25122 23.09 4.08594 22.6913 4.08594 22.2247V5.77467C4.08594 5.30801 4.25122 4.9094 4.58177 4.57884C4.91233 4.24829 5.31094 4.08301 5.7776 4.08301H22.2276C22.6943 4.08301 23.0929 4.24829 23.4234 4.57884C23.754 4.9094 23.9193 5.30801 23.9193 5.77467V22.2247C23.9193 22.6913 23.754 23.09 23.4234 23.4205C23.0929 23.7511 22.6943 23.9163 22.2276 23.9163H5.7776ZM6.5651 22.6038H21.4401V22.3705C20.3512 21.3983 19.1797 20.6643 17.9255 20.1684C16.6714 19.6726 15.3637 19.4247 14.0026 19.4247C12.6609 19.4247 11.3582 19.6677 10.0943 20.1538C8.83038 20.64 7.65399 21.3691 6.5651 22.3413V22.6038ZM14.0609 14.2913C13.3804 14.2913 12.8019 14.058 12.3255 13.5913C11.8491 13.1247 11.6109 12.5511 11.6109 11.8705C11.6109 11.19 11.8491 10.6163 12.3255 10.1497C12.8019 9.68301 13.3707 9.44968 14.0318 9.44968C14.7123 9.44968 15.2908 9.68787 15.7672 10.1643C16.2436 10.6406 16.4818 11.2094 16.4818 11.8705C16.4818 12.5511 16.2436 13.1247 15.7672 13.5913C15.2908 14.058 14.722 14.2913 14.0609 14.2913Z" fill="black"/> +</svg> diff --git a/www/assets/css/src/icons/x.svg b/www/assets/css/src/icons/x.svg new file mode 100644 index 0000000000000000000000000000000000000000..20845d7ede94cc36f113f7a92d9e82d922a0cbe8 --- /dev/null +++ b/www/assets/css/src/icons/x.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M1.32005 15.6122L0.386719 14.6789L7.06589 7.99971L0.386719 1.32054L1.32005 0.387207L7.99922 7.06637L14.6784 0.387207L15.6117 1.32054L8.93255 7.99971L15.6117 14.6789L14.6784 15.6122L7.99922 8.93304L1.32005 15.6122Z" fill="#4859B2"/> +</svg>