diff --git a/scm-core/src/main/java/sonia/scm/security/AccessToken.java b/scm-core/src/main/java/sonia/scm/security/AccessToken.java index c2a5f4b747..ac7700b030 100644 --- a/scm-core/src/main/java/sonia/scm/security/AccessToken.java +++ b/scm-core/src/main/java/sonia/scm/security/AccessToken.java @@ -80,8 +80,20 @@ public interface AccessToken { */ Date getExpiration(); + /** + * Returns refresh expiration of token. + * + * @return refresh expiration + */ Optional getRefreshExpiration(); + /** + * Returns id of the parent key. + * + * @return parent key id + */ + Optional getParentKey(); + /** * Returns the scope of the token. The scope is able to reduce the permissions of the subject in the context of this * token. For example we could issue a token which can only be used to read a single repository. for more informations diff --git a/scm-core/src/main/java/sonia/scm/security/AccessTokenCookieIssuer.java b/scm-core/src/main/java/sonia/scm/security/AccessTokenCookieIssuer.java new file mode 100644 index 0000000000..999c693b8f --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/security/AccessTokenCookieIssuer.java @@ -0,0 +1,30 @@ +package sonia.scm.security; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Generates cookies and invalidates access token cookies. + * + * @author Sebastian Sdorra + * @since 2.0.0 + */ +public interface AccessTokenCookieIssuer { + + /** + * Creates a cookie for token authentication and attaches it to the response. + * + * @param request http servlet request + * @param response http servlet response + * @param accessToken access token + */ + void authenticate(HttpServletRequest request, HttpServletResponse response, AccessToken accessToken); + /** + * Invalidates the authentication cookie. + * + * @param request http servlet request + * @param response http servlet response + */ + void invalidate(HttpServletRequest request, HttpServletResponse response); + +} diff --git a/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java b/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java index b4f0d81cd3..9c1fa590cc 100644 --- a/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java +++ b/scm-core/src/main/java/sonia/scm/security/DefaultCipherHandler.java @@ -164,7 +164,7 @@ public class DefaultCipherHandler implements CipherHandler { String result = null; try { - byte[] encodedInput = Base64.getDecoder().decode(value); + byte[] encodedInput = Base64.getUrlDecoder().decode(value); byte[] salt = new byte[SALT_LENGTH]; byte[] encoded = new byte[encodedInput.length - SALT_LENGTH]; @@ -221,7 +221,7 @@ public class DefaultCipherHandler implements CipherHandler { System.arraycopy(salt, 0, result, 0, SALT_LENGTH); System.arraycopy(encodedInput, 0, result, SALT_LENGTH, result.length - SALT_LENGTH); - res = new String(Base64.getEncoder().encode(result), ENCODING); + res = new String(Base64.getUrlEncoder().encode(result), ENCODING); } catch (IOException | GeneralSecurityException ex) { throw new CipherException("could not encode string", ex); } diff --git a/scm-core/src/main/java/sonia/scm/store/ConfigurationStore.java b/scm-core/src/main/java/sonia/scm/store/ConfigurationStore.java index a7f21dd304..b1c38f1a00 100644 --- a/scm-core/src/main/java/sonia/scm/store/ConfigurationStore.java +++ b/scm-core/src/main/java/sonia/scm/store/ConfigurationStore.java @@ -33,6 +33,10 @@ package sonia.scm.store; +import java.util.Optional; + +import static java.util.Optional.ofNullable; + /** * ConfigurationStore for configuration objects. Note: the default * implementation use JAXB to marshall the configuration objects. @@ -50,7 +54,17 @@ public interface ConfigurationStore * * @return configuration object from store */ - public T get(); + T get(); + + /** + * Returns the configuration object from store. + * + * + * @return configuration object from store + */ + default Optional getOptional() { + return ofNullable(get()); + } //~--- set methods ---------------------------------------------------------- @@ -58,7 +72,7 @@ public interface ConfigurationStore * Stores the given configuration object to the store. * * - * @param obejct configuration object to store + * @param object configuration object to store */ - public void set(T obejct); + void set(T object); } diff --git a/scm-core/src/main/java/sonia/scm/store/MultiEntryStore.java b/scm-core/src/main/java/sonia/scm/store/MultiEntryStore.java index 9a35cee0e0..c1a8863758 100644 --- a/scm-core/src/main/java/sonia/scm/store/MultiEntryStore.java +++ b/scm-core/src/main/java/sonia/scm/store/MultiEntryStore.java @@ -32,6 +32,10 @@ package sonia.scm.store; +import java.util.Optional; + +import static java.util.Optional.ofNullable; + /** * Base class for {@link BlobStore} and {@link DataStore}. * @@ -67,4 +71,16 @@ public interface MultiEntryStore { * @return item with the given id */ public T get(String id); + + /** + * Returns the item with the given id from the store. + * + * + * @param id id of the item to return + * + * @return item with the given id + */ + default Optional getOptional(String id) { + return ofNullable(get(id)); + } } diff --git a/scm-core/src/main/java/sonia/scm/web/AbstractRepositoryJsonEnricher.java b/scm-core/src/main/java/sonia/scm/web/AbstractRepositoryJsonEnricher.java new file mode 100644 index 0000000000..2cb4674d24 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/web/AbstractRepositoryJsonEnricher.java @@ -0,0 +1,40 @@ +package sonia.scm.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import static java.util.Collections.singletonMap; +import static sonia.scm.web.VndMediaType.REPOSITORY; +import static sonia.scm.web.VndMediaType.REPOSITORY_COLLECTION; + +public abstract class AbstractRepositoryJsonEnricher extends JsonEnricherBase { + + public AbstractRepositoryJsonEnricher(ObjectMapper objectMapper) { + super(objectMapper); + } + + @Override + public void enrich(JsonEnricherContext context) { + if (resultHasMediaType(REPOSITORY, context)) { + JsonNode repositoryNode = context.getResponseEntity(); + enrichRepositoryNode(repositoryNode); + } else if (resultHasMediaType(REPOSITORY_COLLECTION, context)) { + JsonNode repositoryCollectionNode = context.getResponseEntity().get("_embedded").withArray("repositories"); + repositoryCollectionNode.elements().forEachRemaining(this::enrichRepositoryNode); + } + } + + private void enrichRepositoryNode(JsonNode repositoryNode) { + String namespace = repositoryNode.get("namespace").asText(); + String name = repositoryNode.get("name").asText(); + + enrichRepositoryNode(repositoryNode, namespace, name); + } + + protected abstract void enrichRepositoryNode(JsonNode repositoryNode, String namespace, String name); + + protected void addLink(JsonNode repositoryNode, String linkName, String link) { + JsonNode hrefNode = createObject(singletonMap("href", value(link))); + addPropertyNode(repositoryNode.get("_links"), linkName, hrefNode); + } +} diff --git a/scm-core/src/main/java/sonia/scm/web/filter/AuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/AuthenticationFilter.java index ffe6ecc787..c6a8463998 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/AuthenticationFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/AuthenticationFilter.java @@ -128,7 +128,7 @@ public class AuthenticationFilter extends HttpFilter } else if (subject.isAuthenticated()) { - logger.trace("user is allready authenticated"); + logger.trace("user is already authenticated"); processChain(request, response, chain, subject); } else if (isAnonymousAccessEnabled()) diff --git a/scm-core/src/main/java/sonia/scm/xml/XmlInstantAdapter.java b/scm-core/src/main/java/sonia/scm/xml/XmlInstantAdapter.java new file mode 100644 index 0000000000..9b8d718851 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/xml/XmlInstantAdapter.java @@ -0,0 +1,25 @@ +package sonia.scm.xml; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; + +/** + * JAXB adapter for {@link Instant} objects. + * + * @since 2.0.0 + */ +public class XmlInstantAdapter extends XmlAdapter { + + @Override + public String marshal(Instant instant) { + return DateTimeFormatter.ISO_INSTANT.format(instant); + } + + @Override + public Instant unmarshal(String text) { + TemporalAccessor parsed = DateTimeFormatter.ISO_INSTANT.parse(text); + return Instant.from(parsed); + } +} diff --git a/scm-core/src/test/java/sonia/scm/web/AbstractRepositoryJsonEnricherTest.java b/scm-core/src/test/java/sonia/scm/web/AbstractRepositoryJsonEnricherTest.java new file mode 100644 index 0000000000..2c8ef76464 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/web/AbstractRepositoryJsonEnricherTest.java @@ -0,0 +1,107 @@ +package sonia.scm.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.io.Resources; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import sonia.scm.api.v2.resources.ScmPathInfoStore; + +import javax.ws.rs.core.MediaType; +import java.io.IOException; +import java.net.URI; +import java.net.URL; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class AbstractRepositoryJsonEnricherTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + private AbstractRepositoryJsonEnricher linkEnricher; + private JsonNode rootNode; + + @BeforeEach + void globalSetUp() { + ScmPathInfoStore pathInfoStore = new ScmPathInfoStore(); + pathInfoStore.set(() -> URI.create("/")); + + linkEnricher = new AbstractRepositoryJsonEnricher(objectMapper) { + @Override + protected void enrichRepositoryNode(JsonNode repositoryNode, String namespace, String name) { + addLink(repositoryNode, "new-link", "/somewhere"); + } + }; + } + + @Test + void shouldEnrichRepositories() throws IOException { + URL resource = Resources.getResource("sonia/scm/repository/repository-001.json"); + rootNode = objectMapper.readTree(resource); + + JsonEnricherContext context = new JsonEnricherContext( + URI.create("/"), + MediaType.valueOf(VndMediaType.REPOSITORY), + rootNode + ); + + linkEnricher.enrich(context); + + String configLink = context.getResponseEntity() + .get("_links") + .get("new-link") + .get("href") + .asText(); + + assertThat(configLink).isEqualTo("/somewhere"); + } + + @Test + void shouldEnrichAllRepositories() throws IOException { + URL resource = Resources.getResource("sonia/scm/repository/repository-collection-001.json"); + rootNode = objectMapper.readTree(resource); + + JsonEnricherContext context = new JsonEnricherContext( + URI.create("/"), + MediaType.valueOf(VndMediaType.REPOSITORY_COLLECTION), + rootNode + ); + + linkEnricher.enrich(context); + + context.getResponseEntity() + .get("_embedded") + .withArray("repositories") + .elements() + .forEachRemaining(node -> { + String configLink = node + .get("_links") + .get("new-link") + .get("href") + .asText(); + + assertThat(configLink).isEqualTo("/somewhere"); + }); + } + + @Test + void shouldNotModifyObjectsWithUnsupportedMediaType() throws IOException { + URL resource = Resources.getResource("sonia/scm/repository/repository-001.json"); + rootNode = objectMapper.readTree(resource); + JsonEnricherContext context = new JsonEnricherContext( + URI.create("/"), + MediaType.valueOf(VndMediaType.USER), + rootNode + ); + + linkEnricher.enrich(context); + + boolean hasNewPullRequestLink = context.getResponseEntity() + .get("_links") + .has("new-link"); + + assertThat(hasNewPullRequestLink).isFalse(); + } +} diff --git a/scm-core/src/test/java/sonia/scm/xml/XmlInstantAdapterTest.java b/scm-core/src/test/java/sonia/scm/xml/XmlInstantAdapterTest.java new file mode 100644 index 0000000000..eb1ea86aee --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/xml/XmlInstantAdapterTest.java @@ -0,0 +1,47 @@ +package sonia.scm.xml; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junitpioneer.jupiter.TempDirectory; + +import javax.xml.bind.JAXB; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.nio.file.Path; +import java.time.Instant; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(TempDirectory.class) +class XmlInstantAdapterTest { + + @Test + void shouldMarshalAndUnmarshalInstant(@TempDirectory.TempDir Path tempDirectory) { + Path path = tempDirectory.resolve("instant.xml"); + + Instant instant = Instant.now(); + InstantObject object = new InstantObject(instant); + JAXB.marshal(object, path.toFile()); + + InstantObject unmarshaled = JAXB.unmarshal(path.toFile(), InstantObject.class); + assertEquals(instant, unmarshaled.instant); + } + + @XmlRootElement(name = "instant-object") + @XmlAccessorType(XmlAccessType.FIELD) + public static class InstantObject { + + @XmlJavaTypeAdapter(XmlInstantAdapter.class) + private Instant instant; + + public InstantObject() { + } + + InstantObject(Instant instant) { + this.instant = instant; + } + } + +} diff --git a/scm-core/src/test/resources/sonia/scm/repository/repository-001.json b/scm-core/src/test/resources/sonia/scm/repository/repository-001.json new file mode 100644 index 0000000000..43ea136942 --- /dev/null +++ b/scm-core/src/test/resources/sonia/scm/repository/repository-001.json @@ -0,0 +1,42 @@ +{ + "creationDate": "2018-11-09T09:48:32.732Z", + "description": "Handling static webresources made easy", + "healthCheckFailures": [], + "lastModified": "2018-11-09T09:49:20.973Z", + "namespace": "scmadmin", + "name": "web-resources", + "archived": false, + "type": "git", + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "delete": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "update": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "permissions": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/" + }, + "protocol": [ + { + "href": "http://localhost:8081/scm/repo/scmadmin/web-resources", + "name": "http" + } + ], + "tags": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/" + }, + "branches": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/" + }, + "changesets": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/" + }, + "sources": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/" + } + } +} diff --git a/scm-core/src/test/resources/sonia/scm/repository/repository-collection-001.json b/scm-core/src/test/resources/sonia/scm/repository/repository-collection-001.json new file mode 100644 index 0000000000..f4eeb24bbc --- /dev/null +++ b/scm-core/src/test/resources/sonia/scm/repository/repository-collection-001.json @@ -0,0 +1,106 @@ +{ + "page": 0, + "pageTotal": 1, + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10" + }, + "first": { + "href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10" + }, + "last": { + "href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10" + }, + "create": { + "href": "http://localhost:8081/scm/api/v2/repositories/" + } + }, + "_embedded": { + "repositories": [ + { + "creationDate": "2018-11-09T09:48:32.732Z", + "description": "Handling static webresources made easy", + "healthCheckFailures": [], + "lastModified": "2018-11-09T09:49:20.973Z", + "namespace": "scmadmin", + "name": "web-resources", + "archived": false, + "type": "git", + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "delete": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "update": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "permissions": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/" + }, + "protocol": [ + { + "href": "http://localhost:8081/scm/repo/scmadmin/web-resources", + "name": "http" + } + ], + "tags": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/" + }, + "branches": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/" + }, + "changesets": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/" + }, + "sources": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/" + } + } + }, + { + "creationDate": "2018-11-09T09:48:32.732Z", + "description": "Handling static webresources made easy", + "healthCheckFailures": [], + "lastModified": "2018-11-09T09:49:20.973Z", + "namespace": "scmadmin", + "name": "web-resources", + "archived": false, + "type": "git", + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "delete": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "update": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "permissions": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/" + }, + "protocol": [ + { + "href": "http://localhost:8081/scm/repo/scmadmin/web-resources", + "name": "http" + } + ], + "tags": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/" + }, + "branches": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/" + }, + "changesets": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/" + }, + "sources": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/" + } + } + } + ] + } +} diff --git a/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java b/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java index 099ab53baa..d37a150723 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java +++ b/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java @@ -58,8 +58,6 @@ public abstract class FileBasedStoreFactory { private RepositoryLocationResolver repositoryLocationResolver; private Store store; - private File storeDirectory; - protected FileBasedStoreFactory(SCMContextProvider contextProvider , RepositoryLocationResolver repositoryLocationResolver, Store store) { this.contextProvider = contextProvider; this.repositoryLocationResolver = repositoryLocationResolver; @@ -75,17 +73,16 @@ public abstract class FileBasedStoreFactory { } protected File getStoreLocation(String name, Class type, Repository repository) { - if (storeDirectory == null) { - if (repository != null) { - LOG.debug("create store with type: {}, name: {} and repository: {}", type, name, repository.getNamespaceAndName()); - storeDirectory = this.getStoreDirectory(store, repository); - } else { - LOG.debug("create store with type: {} and name: {} ", type, name); - storeDirectory = this.getStoreDirectory(store); - } - IOUtil.mkdirs(storeDirectory); + File storeDirectory; + if (repository != null) { + LOG.debug("create store with type: {}, name: {} and repository: {}", type, name, repository.getNamespaceAndName()); + storeDirectory = this.getStoreDirectory(store, repository); + } else { + LOG.debug("create store with type: {} and name: {} ", type, name); + storeDirectory = this.getStoreDirectory(store); } - return new File(this.storeDirectory, name); + IOUtil.mkdirs(storeDirectory); + return new File(storeDirectory, name); } /** diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java index 1384d73d9c..e078b04b08 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitConfigResource.java @@ -9,13 +9,17 @@ import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.web.GitVndMediaType; import javax.inject.Inject; +import javax.inject.Provider; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; +import static sonia.scm.ContextEntry.ContextBuilder.entity; + /** * RESTful Web Service Resource to manage the configuration of the git plugin. */ @@ -26,13 +30,15 @@ public class GitConfigResource { private final GitConfigDtoToGitConfigMapper dtoToConfigMapper; private final GitConfigToGitConfigDtoMapper configToDtoMapper; private final GitRepositoryHandler repositoryHandler; + private final Provider gitRepositoryConfigResource; @Inject public GitConfigResource(GitConfigDtoToGitConfigMapper dtoToConfigMapper, GitConfigToGitConfigDtoMapper configToDtoMapper, - GitRepositoryHandler repositoryHandler) { + GitRepositoryHandler repositoryHandler, Provider gitRepositoryConfigResource) { this.dtoToConfigMapper = dtoToConfigMapper; this.configToDtoMapper = configToDtoMapper; this.repositoryHandler = repositoryHandler; + this.gitRepositoryConfigResource = gitRepositoryConfigResource; } /** @@ -88,4 +94,9 @@ public class GitConfigResource { return Response.noContent().build(); } + + @Path("{namespace}/{name}") + public GitRepositoryConfigResource getRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name) { + return gitRepositoryConfigResource.get(); + } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangeClearRepositoryCacheListener.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangeClearRepositoryCacheListener.java new file mode 100644 index 0000000000..df93fa4886 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangeClearRepositoryCacheListener.java @@ -0,0 +1,19 @@ +package sonia.scm.api.v2.resources; + +import com.github.legman.Subscribe; +import sonia.scm.EagerSingleton; +import sonia.scm.event.ScmEventBus; +import sonia.scm.plugin.Extension; +import sonia.scm.repository.ClearRepositoryCacheEvent; + +import java.util.Objects; + +@EagerSingleton @Extension +public class GitRepositoryConfigChangeClearRepositoryCacheListener { + @Subscribe + public void sendClearRepositoryCacheEvent(GitRepositoryConfigChangedEvent event) { + if (!Objects.equals(event.getOldConfig().getDefaultBranch(), event.getNewConfig().getDefaultBranch())) { + ScmEventBus.getInstance().post(new ClearRepositoryCacheEvent(event.getRepository())); + } + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangedEvent.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangedEvent.java new file mode 100644 index 0000000000..eaf575a610 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigChangedEvent.java @@ -0,0 +1,30 @@ +package sonia.scm.api.v2.resources; + +import sonia.scm.event.Event; +import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.repository.Repository; + +@Event +public class GitRepositoryConfigChangedEvent { + private final Repository repository; + private final GitRepositoryConfig oldConfig; + private final GitRepositoryConfig newConfig; + + public GitRepositoryConfigChangedEvent(Repository repository, GitRepositoryConfig oldConfig, GitRepositoryConfig newConfig) { + this.repository = repository; + this.oldConfig = oldConfig; + this.newConfig = newConfig; + } + + public Repository getRepository() { + return repository; + } + + public GitRepositoryConfig getOldConfig() { + return oldConfig; + } + + public GitRepositoryConfig getNewConfig() { + return newConfig; + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigDto.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigDto.java new file mode 100644 index 0000000000..d22d6c194e --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigDto.java @@ -0,0 +1,24 @@ +package sonia.scm.api.v2.resources; + +import de.otto.edison.hal.HalRepresentation; +import de.otto.edison.hal.Links; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@SuppressWarnings("squid:S2160") // there is no proper semantic for equals on this dto +public class GitRepositoryConfigDto extends HalRepresentation { + + private String defaultBranch; + + @Override + @SuppressWarnings("squid:S1185") // We want to have this method available in this package + protected HalRepresentation add(Links links) { + return super.add(links); + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigEnricher.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigEnricher.java new file mode 100644 index 0000000000..2566fd82f7 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigEnricher.java @@ -0,0 +1,37 @@ +package sonia.scm.api.v2.resources; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import sonia.scm.plugin.Extension; +import sonia.scm.repository.GitRepositoryHandler; +import sonia.scm.repository.NamespaceAndName; +import sonia.scm.repository.RepositoryManager; +import sonia.scm.web.AbstractRepositoryJsonEnricher; + +import javax.inject.Inject; +import javax.inject.Provider; + +@Extension +public class GitRepositoryConfigEnricher extends AbstractRepositoryJsonEnricher { + + private final Provider scmPathInfoStore; + private final RepositoryManager manager; + + @Inject + public GitRepositoryConfigEnricher(Provider scmPathInfoStore, ObjectMapper objectMapper, RepositoryManager manager) { + super(objectMapper); + this.scmPathInfoStore = scmPathInfoStore; + this.manager = manager; + } + + @Override + protected void enrichRepositoryNode(JsonNode repositoryNode, String namespace, String name) { + if (GitRepositoryHandler.TYPE_NAME.equals(manager.get(new NamespaceAndName(namespace, name)).getType())) { + String repositoryConfigLink = new LinkBuilder(scmPathInfoStore.get().get(), GitConfigResource.class) + .method("getRepositoryConfig") + .parameters(namespace, name) + .href(); + addLink(repositoryNode, "configuration", repositoryConfigLink); + } + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigMapper.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigMapper.java new file mode 100644 index 0000000000..6480e526b1 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigMapper.java @@ -0,0 +1,46 @@ +package sonia.scm.api.v2.resources; + +import de.otto.edison.hal.Links; +import org.mapstruct.AfterMapping; +import org.mapstruct.Context; +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryPermissions; + +import javax.inject.Inject; + +import static de.otto.edison.hal.Link.link; +import static de.otto.edison.hal.Links.linkingTo; + +// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection. +@SuppressWarnings("squid:S3306") +@Mapper +public abstract class GitRepositoryConfigMapper { + + @Inject + private ScmPathInfoStore scmPathInfoStore; + + public abstract GitRepositoryConfigDto map(GitRepositoryConfig config, @Context Repository repository); + public abstract GitRepositoryConfig map(GitRepositoryConfigDto dto); + + @AfterMapping + void appendLinks(@MappingTarget GitRepositoryConfigDto target, @Context Repository repository) { + Links.Builder linksBuilder = linkingTo().self(self()); + if (RepositoryPermissions.modify(repository).isPermitted()) { + linksBuilder.single(link("update", update())); + } + target.add(linksBuilder.build()); + } + + private String self() { + LinkBuilder linkBuilder = new LinkBuilder(scmPathInfoStore.get(), GitConfigResource.class); + return linkBuilder.method("get").parameters().href(); + } + + private String update() { + LinkBuilder linkBuilder = new LinkBuilder(scmPathInfoStore.get(), GitConfigResource.class); + return linkBuilder.method("update").parameters().href(); + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigResource.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigResource.java new file mode 100644 index 0000000000..7b226186e5 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigResource.java @@ -0,0 +1,90 @@ +package sonia.scm.api.v2.resources; + +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.repository.NamespaceAndName; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryManager; +import sonia.scm.store.ConfigurationStore; +import sonia.scm.web.GitVndMediaType; + +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +import static sonia.scm.ContextEntry.ContextBuilder.entity; +import static sonia.scm.NotFoundException.notFound; + +public class GitRepositoryConfigResource { + + private static final Logger LOG = LoggerFactory.getLogger(GitRepositoryConfigResource.class); + + private final GitRepositoryConfigMapper repositoryConfigMapper; + private final RepositoryManager repositoryManager; + private final GitRepositoryConfigStoreProvider gitRepositoryConfigStoreProvider; + + @Inject + public GitRepositoryConfigResource(GitRepositoryConfigMapper repositoryConfigMapper, RepositoryManager repositoryManager, GitRepositoryConfigStoreProvider gitRepositoryConfigStoreProvider) { + this.repositoryConfigMapper = repositoryConfigMapper; + this.repositoryManager = repositoryManager; + this.gitRepositoryConfigStoreProvider = gitRepositoryConfigStoreProvider; + } + + @GET + @Path("/") + @Produces(GitVndMediaType.GIT_REPOSITORY_CONFIG) + @StatusCodes({ + @ResponseCode(code = 200, condition = "success"), + @ResponseCode(code = 401, condition = "not authenticated / invalid credentials"), + @ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the repository config"), + @ResponseCode(code = 404, condition = "not found, no repository with the specified namespace and name available"), + @ResponseCode(code = 500, condition = "internal server error") + }) + public Response getRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name) { + Repository repository = getRepository(namespace, name); + ConfigurationStore repositoryConfigStore = getStore(repository); + GitRepositoryConfig config = repositoryConfigStore.get(); + GitRepositoryConfigDto dto = repositoryConfigMapper.map(config, repository); + return Response.ok(dto).build(); + } + + @PUT + @Path("/") + @Consumes(GitVndMediaType.GIT_REPOSITORY_CONFIG) + @StatusCodes({ + @ResponseCode(code = 204, condition = "update success"), + @ResponseCode(code = 401, condition = "not authenticated / invalid credentials"), + @ResponseCode(code = 403, condition = "not authorized, the current user does not have the privilege to change this repositories config"), + @ResponseCode(code = 404, condition = "not found, no repository with the specified namespace and name available/name available"), + @ResponseCode(code = 500, condition = "internal server error") + }) + public Response setRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name, GitRepositoryConfigDto dto) { + Repository repository = getRepository(namespace, name); + ConfigurationStore repositoryConfigStore = getStore(repository); + GitRepositoryConfig config = repositoryConfigMapper.map(dto); + repositoryConfigStore.set(config); + LOG.info("git default branch of repository {} has changed, sending clear cache event", repository.getNamespaceAndName()); + return Response.noContent().build(); + } + + private Repository getRepository(@PathParam("namespace") String namespace, @PathParam("name") String name) { + NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name); + Repository repository = repositoryManager.get(namespaceAndName); + if (repository == null) { + throw notFound(entity(namespaceAndName)); + } + return repository; + } + + private ConfigurationStore getStore(Repository repository) { + return gitRepositoryConfigStoreProvider.get(repository); + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigStoreProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigStoreProvider.java new file mode 100644 index 0000000000..ce37fb65f4 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/api/v2/resources/GitRepositoryConfigStoreProvider.java @@ -0,0 +1,50 @@ +package sonia.scm.api.v2.resources; + +import sonia.scm.event.ScmEventBus; +import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.repository.Repository; +import sonia.scm.store.ConfigurationStore; +import sonia.scm.store.ConfigurationStoreFactory; + +import javax.inject.Inject; + +public class GitRepositoryConfigStoreProvider { + + private final ConfigurationStoreFactory configurationStoreFactory; + + @Inject + public GitRepositoryConfigStoreProvider(ConfigurationStoreFactory configurationStoreFactory) { + this.configurationStoreFactory = configurationStoreFactory; + } + + public ConfigurationStore get(Repository repository) { + return new StoreWrapper(configurationStoreFactory.withType(GitRepositoryConfig.class).withName("gitConfig").forRepository(repository).build(), repository); + } + + private static class StoreWrapper implements ConfigurationStore { + + private final ConfigurationStore delegate; + private final Repository repository; + + private StoreWrapper(ConfigurationStore delegate, Repository repository) { + this.delegate = delegate; + this.repository = repository; + } + + @Override + public GitRepositoryConfig get() { + GitRepositoryConfig config = delegate.get(); + if (config == null) { + return new GitRepositoryConfig(); + } + return config; + } + + @Override + public void set(GitRepositoryConfig newConfig) { + GitRepositoryConfig oldConfig = get(); + delegate.set(newConfig); + ScmEventBus.getInstance().post(new GitRepositoryConfigChangedEvent(repository, oldConfig, newConfig)); + } + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitConstants.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitConstants.java deleted file mode 100644 index 6d833577e1..0000000000 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitConstants.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2014, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ -package sonia.scm.repository; - -/** - * Constants for Git. - * - * @author Sebastian Sdorra - * @since 1.50 - */ -public final class GitConstants { - - /** - * Default branch repository property. - */ - public static final String PROPERTY_DEFAULT_BRANCH = "git.default-branch"; - - private GitConstants() { - } - -} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitHeadModifier.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitHeadModifier.java new file mode 100644 index 0000000000..b82e8bdd3c --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitHeadModifier.java @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2014, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ +package sonia.scm.repository; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.RefUpdate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import java.io.File; +import java.io.IOException; +import java.util.Objects; + +/** + * The GitHeadModifier is able to modify the head of a git repository. + * + * @author Sebastian Sdorra + * @since 1.61 + */ +public class GitHeadModifier { + + private static final Logger LOG = LoggerFactory.getLogger(GitHeadModifier.class); + + private final GitRepositoryHandler repositoryHandler; + + @Inject + public GitHeadModifier(GitRepositoryHandler repositoryHandler) { + this.repositoryHandler = repositoryHandler; + } + + /** + * Ensures that the repositories head points to the given branch. The method will return {@code false} if the + * repositories head points already to the given branch. + * + * @param repository repository to modify + * @param newHead branch which should be the new head of the repository + * + * @return {@code true} if the head has changed + */ + public boolean ensure(Repository repository, String newHead) { + try (org.eclipse.jgit.lib.Repository gitRepository = open(repository)) { + String currentHead = resolve(gitRepository); + if (!Objects.equals(currentHead, newHead)) { + return modify(gitRepository, newHead); + } + } catch (IOException ex) { + LOG.warn("failed to change head of repository", ex); + } + return false; + } + + private String resolve(org.eclipse.jgit.lib.Repository gitRepository) throws IOException { + Ref ref = gitRepository.getRefDatabase().getRef(Constants.HEAD); + if ( ref.isSymbolic() ) { + ref = ref.getTarget(); + } + return GitUtil.getBranch(ref); + } + + private boolean modify(org.eclipse.jgit.lib.Repository gitRepository, String newHead) throws IOException { + RefUpdate refUpdate = gitRepository.getRefDatabase().newUpdate(Constants.HEAD, true); + refUpdate.setForceUpdate(true); + RefUpdate.Result result = refUpdate.link(Constants.R_HEADS + newHead); + return result == RefUpdate.Result.FORCED; + } + + private org.eclipse.jgit.lib.Repository open(Repository repository) throws IOException { + File directory = repositoryHandler.getDirectory(repository.getId()); + return GitUtil.open(directory); + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryConfig.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryConfig.java new file mode 100644 index 0000000000..a0136c8ea6 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryConfig.java @@ -0,0 +1,27 @@ +package sonia.scm.repository; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "config") +@XmlAccessorType(XmlAccessType.FIELD) +public class GitRepositoryConfig { + + public GitRepositoryConfig() { + } + + public GitRepositoryConfig(String defaultBranch) { + this.defaultBranch = defaultBranch; + } + + private String defaultBranch; + + public String getDefaultBranch() { + return defaultBranch; + } + + public void setDefaultBranch(String defaultBranch) { + this.defaultBranch = defaultBranch; + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java index 1cbcdc35bf..a16b34f6be 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitRepositoryModifyListener.java @@ -31,67 +31,45 @@ package sonia.scm.repository; import com.github.legman.Subscribe; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Objects; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import sonia.scm.EagerSingleton; -import sonia.scm.HandlerEventType; -import sonia.scm.event.ScmEventBus; +import sonia.scm.api.v2.resources.GitRepositoryConfigChangedEvent; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.plugin.Extension; +import javax.inject.Inject; + /** * Repository listener which handles git related repository events. - * + * * @author Sebastian Sdorra * @since 1.50 */ @Extension @EagerSingleton public class GitRepositoryModifyListener { - - /** - * the logger for GitRepositoryModifyListener - */ - private static final Logger logger = LoggerFactory.getLogger(GitRepositoryModifyListener.class); - + + private final GitHeadModifier headModifier; + private final GitRepositoryConfigStoreProvider storeProvider; + + @Inject + public GitRepositoryModifyListener(GitHeadModifier headModifier, GitRepositoryConfigStoreProvider storeProvider) { + this.headModifier = headModifier; + this.storeProvider = storeProvider; + } + /** * Receives {@link RepositoryModificationEvent} and fires a {@link ClearRepositoryCacheEvent} if * the default branch of a git repository was modified. - * + * * @param event repository modification event */ @Subscribe - public void handleEvent(RepositoryModificationEvent event){ - Repository repository = event.getItem(); - - if ( isModifyEvent(event) && - isGitRepository(event.getItem()) && - hasDefaultBranchChanged(event.getItemBeforeModification(), repository)) - { - logger.info("git default branch of repository {} has changed, sending clear cache event", repository.getId()); - sendClearRepositoryCacheEvent(repository); + public void handleEvent(GitRepositoryConfigChangedEvent event){ + Repository repository = event.getRepository(); + + String defaultBranch = storeProvider.get(repository).get().getDefaultBranch(); + if (defaultBranch != null) { + headModifier.ensure(repository, defaultBranch); } } - - @VisibleForTesting - protected void sendClearRepositoryCacheEvent(Repository repository) { - ScmEventBus.getInstance().post(new ClearRepositoryCacheEvent(repository)); - } - - private boolean isModifyEvent(RepositoryEvent event) { - return event.getEventType() == HandlerEventType.MODIFY; - } - - private boolean isGitRepository(Repository repository) { - return GitRepositoryHandler.TYPE_NAME.equals(repository.getType()); - } - - private boolean hasDefaultBranchChanged(Repository old, Repository current) { - return !Objects.equal( - old.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH), - current.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH) - ); - } - } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index 2970bbd627..f94ccd59f6 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -40,7 +40,6 @@ import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sonia.scm.repository.GitConstants; import sonia.scm.repository.GitUtil; import java.io.IOException; @@ -110,7 +109,7 @@ public class AbstractGitCommand protected Ref getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException { if ( Strings.isNullOrEmpty(requestedBranch) ) { - String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); + String defaultBranchName = context.getConfig().getDefaultBranch(); if (!Strings.isNullOrEmpty(defaultBranchName)) { return GitUtil.getBranchId(gitRepository, defaultBranchName); } else { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitContext.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitContext.java index b0dd8f1fd6..0b93f9cf2b 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitContext.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitContext.java @@ -37,6 +37,8 @@ package sonia.scm.repository.spi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; +import sonia.scm.repository.GitRepositoryConfig; import sonia.scm.repository.GitUtil; import sonia.scm.repository.Repository; @@ -68,10 +70,11 @@ public class GitContext implements Closeable * @param directory * @param repository */ - public GitContext(File directory, Repository repository) + public GitContext(File directory, Repository repository, GitRepositoryConfigStoreProvider storeProvider) { this.directory = directory; this.repository = repository; + this.storeProvider = storeProvider; } //~--- methods -------------------------------------------------------------- @@ -117,11 +120,25 @@ public class GitContext implements Closeable return directory; } + GitRepositoryConfig getConfig() { + GitRepositoryConfig config = storeProvider.get(repository).get(); + if (config == null) { + return new GitRepositoryConfig(); + } else { + return config; + } + } + + void setConfig(GitRepositoryConfig newConfig) { + storeProvider.get(repository).set(newConfig); + } + //~--- fields --------------------------------------------------------------- /** Field description */ private final File directory; private final Repository repository; + private final GitRepositoryConfigStoreProvider storeProvider; /** Field description */ private org.eclipse.jgit.lib.Repository gitRepository; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java index 2ea25126cf..a6f74d24eb 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java @@ -205,7 +205,7 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand ObjectId ancestorId = null; if (!Strings.isNullOrEmpty(request.getAncestorChangeset())) { - ancestorId = computeCommonAncestor(request, repository, startId, branch); + ancestorId = repository.resolve(request.getAncestorChangeset()); } revWalk = new RevWalk(repository); @@ -225,16 +225,15 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand revWalk.markStart(revWalk.lookupCommit(branch.getObjectId())); } + if (ancestorId != null) { + revWalk.markUninteresting(revWalk.lookupCommit(ancestorId)); + } Iterator iterator = revWalk.iterator(); while (iterator.hasNext()) { RevCommit commit = iterator.next(); - if (commit.getId().equals(ancestorId)) { - break; - } - if ((counter >= start) && ((limit < 0) || (counter < start + limit))) { changesetList.add(converter.createChangeset(commit)); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index 936962eaba..ef3d96d5cb 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -34,6 +34,7 @@ package sonia.scm.repository.spi; import com.google.common.collect.ImmutableSet; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.repository.Feature; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; @@ -73,10 +74,10 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- - public GitRepositoryServiceProvider(GitRepositoryHandler handler, Repository repository) { + public GitRepositoryServiceProvider(GitRepositoryHandler handler, Repository repository, GitRepositoryConfigStoreProvider storeProvider) { this.handler = handler; this.repository = repository; - this.context = new GitContext(handler.getDirectory(repository.getId()), repository); + this.context = new GitContext(handler.getDirectory(repository.getId()), repository, storeProvider); } //~--- methods -------------------------------------------------------------- diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java index deca141556..0730ffc9cf 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceResolver.java @@ -35,6 +35,7 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.Inject; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.plugin.Extension; import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.Repository; @@ -47,10 +48,12 @@ import sonia.scm.repository.Repository; public class GitRepositoryServiceResolver implements RepositoryServiceResolver { private final GitRepositoryHandler handler; + private final GitRepositoryConfigStoreProvider storeProvider; @Inject - public GitRepositoryServiceResolver(GitRepositoryHandler handler) { + public GitRepositoryServiceResolver(GitRepositoryHandler handler, GitRepositoryConfigStoreProvider storeProvider) { this.handler = handler; + this.storeProvider = storeProvider; } @Override @@ -58,7 +61,7 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver { GitRepositoryServiceProvider provider = null; if (GitRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) { - provider = new GitRepositoryServiceProvider(handler, repository); + provider = new GitRepositoryServiceProvider(handler, repository, storeProvider); } return provider; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java index a3dac0e7d1..0bbb993cc6 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitServletModule.java @@ -40,6 +40,7 @@ import org.eclipse.jgit.transport.ScmTransportProtocol; import org.mapstruct.factory.Mappers; import sonia.scm.api.v2.resources.GitConfigDtoToGitConfigMapper; import sonia.scm.api.v2.resources.GitConfigToGitConfigDtoMapper; +import sonia.scm.api.v2.resources.GitRepositoryConfigMapper; import sonia.scm.plugin.Extension; import sonia.scm.repository.GitWorkdirFactory; import sonia.scm.repository.spi.SimpleGitWorkdirFactory; @@ -65,6 +66,7 @@ public class GitServletModule extends ServletModule bind(GitConfigDtoToGitConfigMapper.class).to(Mappers.getMapper(GitConfigDtoToGitConfigMapper.class).getClass()); bind(GitConfigToGitConfigDtoMapper.class).to(Mappers.getMapper(GitConfigToGitConfigDtoMapper.class).getClass()); + bind(GitRepositoryConfigMapper.class).to(Mappers.getMapper(GitRepositoryConfigMapper.class).getClass()); bind(GitWorkdirFactory.class).to(SimpleGitWorkdirFactory.class); } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitVndMediaType.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitVndMediaType.java index 8c81c6eefa..9bfa9fe63e 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitVndMediaType.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/GitVndMediaType.java @@ -2,6 +2,7 @@ package sonia.scm.web; public class GitVndMediaType { public static final String GIT_CONFIG = VndMediaType.PREFIX + "gitConfig" + VndMediaType.SUFFIX; + public static final String GIT_REPOSITORY_CONFIG = VndMediaType.PREFIX + "gitConfig" + VndMediaType.SUFFIX; private GitVndMediaType() { } diff --git a/scm-plugins/scm-git-plugin/src/main/js/RepositoryConfig.js b/scm-plugins/scm-git-plugin/src/main/js/RepositoryConfig.js new file mode 100644 index 0000000000..e34a0ef96f --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/main/js/RepositoryConfig.js @@ -0,0 +1,155 @@ +// @flow + +import React from "react"; + +import {apiClient, BranchSelector, ErrorPage, Loading, SubmitButton} from "@scm-manager/ui-components"; +import type {Branch, Repository} from "@scm-manager/ui-types"; +import {translate} from "react-i18next"; + +type Props = { + repository: Repository, + t: string => string +}; + +type State = { + loadingBranches: boolean, + loadingDefaultBranch: boolean, + submitPending: boolean, + error?: Error, + branches: Branch[], + selectedBranchName?: string, + defaultBranchChanged: boolean +}; + +const GIT_CONFIG_CONTENT_TYPE = "application/vnd.scmm-gitConfig+json"; + +class RepositoryConfig extends React.Component { + + constructor(props: Props) { + super(props); + + this.state = { + loadingBranches: true, + loadingDefaultBranch: true, + submitPending: false, + branches: [], + defaultBranchChanged: false + }; + } + + componentDidMount() { + const { repository } = this.props; + this.setState({ ...this.state, loadingBranches: true }); + apiClient + .get(repository._links.branches.href) + .then(response => response.json()) + .then(payload => payload._embedded.branches) + .then(branches => + this.setState({ ...this.state, branches, loadingBranches: false }) + ) + .catch(error => this.setState({ ...this.state, error })); + + this.setState({ ...this.state, loadingDefaultBranch: true }); + apiClient + .get(repository._links.configuration.href) + .then(response => response.json()) + .then(payload => payload.defaultBranch) + .then(selectedBranchName => + this.setState({ + ...this.state, + selectedBranchName, + loadingDefaultBranch: false + }) + ) + .catch(error => this.setState({ ...this.state, error })); + } + + branchSelected = (branch: Branch) => { + if (!branch) { + this.setState({ ...this.state, selectedBranchName: undefined, defaultBranchChanged: false}); + return; + } + this.setState({ ...this.state, selectedBranchName: branch.name, defaultBranchChanged: false }); + }; + + submit = (event: Event) => { + event.preventDefault(); + + const { repository } = this.props; + const newConfig = { + defaultBranch: this.state.selectedBranchName + }; + this.setState({ ...this.state, submitPending: true }); + apiClient + .put( + repository._links.configuration.href, + newConfig, + GIT_CONFIG_CONTENT_TYPE + ) + .then(() => + this.setState({ + ...this.state, + submitPending: false, + defaultBranchChanged: true + }) + ) + .catch(error => this.setState({ ...this.state, error })); + }; + + render() { + const { t } = this.props; + const { loadingBranches, loadingDefaultBranch, submitPending, error } = this.state; + + if (error) { + return ( + + ); + } + + if (!(loadingBranches || loadingDefaultBranch)) { + return ( + <> + {this.renderBranchChangedNotification()} +
+ + + + + ); + } else { + return ; + } + } + + renderBranchChangedNotification = () => { + if (this.state.defaultBranchChanged) { + return ( +
+
+ ); + } + return null; + }; +} + +export default translate("plugins")(RepositoryConfig); diff --git a/scm-plugins/scm-git-plugin/src/main/js/index.js b/scm-plugins/scm-git-plugin/src/main/js/index.js index bdeda4cd0e..a066247dde 100644 --- a/scm-plugins/scm-git-plugin/src/main/js/index.js +++ b/scm-plugins/scm-git-plugin/src/main/js/index.js @@ -1,11 +1,13 @@ //@flow -import { binder } from "@scm-manager/ui-extensions"; +import React from "react"; +import {binder} from "@scm-manager/ui-extensions"; import ProtocolInformation from "./ProtocolInformation"; import GitAvatar from "./GitAvatar"; -import { ConfigurationBinder as cfgBinder } from "@scm-manager/ui-components"; +import {ConfigurationBinder as cfgBinder} from "@scm-manager/ui-components"; import GitGlobalConfiguration from "./GitGlobalConfiguration"; import GitMergeInformation from "./GitMergeInformation"; +import RepositoryConfig from "./RepositoryConfig"; // repository @@ -13,10 +15,29 @@ const gitPredicate = (props: Object) => { return props.repository && props.repository.type === "git"; }; -binder.bind("repos.repository-details.information", ProtocolInformation, gitPredicate); -binder.bind("repos.repository-merge.information", GitMergeInformation, gitPredicate); +binder.bind( + "repos.repository-details.information", + ProtocolInformation, + gitPredicate +); +binder.bind( + "repos.repository-merge.information", + GitMergeInformation, + gitPredicate +); binder.bind("repos.repository-avatar", GitAvatar, gitPredicate); +cfgBinder.bindRepository( + "/configuration", + "scm-git-plugin.repo-config.link", + "configuration", + RepositoryConfig +); // global config -cfgBinder.bindGlobal("/git", "scm-git-plugin.config.link", "gitConfig", GitGlobalConfiguration); +cfgBinder.bindGlobal( + "/git", + "scm-git-plugin.config.link", + "gitConfig", + GitGlobalConfiguration +); diff --git a/scm-plugins/scm-git-plugin/src/main/resources/locales/en/plugins.json b/scm-plugins/scm-git-plugin/src/main/resources/locales/en/plugins.json index c02cd9e101..a84f44726f 100644 --- a/scm-plugins/scm-git-plugin/src/main/resources/locales/en/plugins.json +++ b/scm-plugins/scm-git-plugin/src/main/resources/locales/en/plugins.json @@ -1,9 +1,9 @@ { "scm-git-plugin": { "information": { - "clone" : "Clone the repository", - "create" : "Create a new repository", - "replace" : "Push an existing repository", + "clone": "Clone the repository", + "create": "Create a new repository", + "replace": "Push an existing repository", "merge": { "heading": "How to merge source branch into target branch", "checkout": "1. Make sure your workspace is clean and checkout target branch", @@ -22,6 +22,16 @@ "disabled": "Disabled", "disabledHelpText": "Enable or disable the Git plugin", "submit": "Submit" + }, + "repo-config": { + "link": "Configuration", + "default-branch": "Default branch", + "submit": "Submit", + "error": { + "title": "Error", + "subtitle": "Something went wrong" + }, + "success": "Default branch changed!" } } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java index 5bf68d3827..0c28a28e59 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitConfigResourceTest.java @@ -1,7 +1,5 @@ package sonia.scm.api.v2.resources; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import org.jboss.resteasy.core.Dispatcher; @@ -14,22 +12,33 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Answers; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.runners.MockitoJUnitRunner; import sonia.scm.repository.GitConfig; +import sonia.scm.repository.GitRepositoryConfig; import sonia.scm.repository.GitRepositoryHandler; +import sonia.scm.repository.NamespaceAndName; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryManager; +import sonia.scm.store.ConfigurationStore; +import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.web.GitVndMediaType; import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import static com.google.inject.util.Providers.of; import static junit.framework.TestCase.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @SubjectAware( @@ -55,30 +64,48 @@ public class GitConfigResourceTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private ScmPathInfoStore scmPathInfoStore; + @Mock + private RepositoryManager repositoryManager; + @InjectMocks private GitConfigToGitConfigDtoMapperImpl configToDtoMapper; + @InjectMocks + private GitRepositoryConfigMapperImpl repositoryConfigMapper; @Mock private GitRepositoryHandler repositoryHandler; + @Mock(answer = Answers.CALLS_REAL_METHODS) + private ConfigurationStoreFactory configurationStoreFactory; + @Spy + private ConfigurationStore configurationStore; + @Captor + private ArgumentCaptor configurationStoreCaptor; + @Before public void prepareEnvironment() { GitConfig gitConfig = createConfiguration(); when(repositoryHandler.getConfig()).thenReturn(gitConfig); - GitConfigResource gitConfigResource = new GitConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler); + GitRepositoryConfigResource gitRepositoryConfigResource = new GitRepositoryConfigResource(repositoryConfigMapper, repositoryManager, new GitRepositoryConfigStoreProvider(configurationStoreFactory)); + GitConfigResource gitConfigResource = new GitConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, of(gitRepositoryConfigResource)); dispatcher.getRegistry().addSingletonResource(gitConfigResource); when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); } + @Before + public void initConfigStore() { + when(configurationStoreFactory.getStore(any())).thenReturn(configurationStore); + doNothing().when(configurationStore).set(configurationStoreCaptor.capture()); + } + @Test @SubjectAware(username = "readWrite") - public void shouldGetGitConfig() throws URISyntaxException, IOException { + public void shouldGetGitConfig() throws URISyntaxException { MockHttpResponse response = get(); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); String responseString = response.getContentAsString(); - ObjectNode responseJson = new ObjectMapper().readValue(responseString, ObjectNode.class); assertTrue(responseString.contains("\"disabled\":false")); assertTrue(responseString.contains("\"gcExpression\":\"valid Git GC Cron Expression\"")); @@ -88,7 +115,7 @@ public class GitConfigResourceTest { @Test @SubjectAware(username = "readWrite") - public void shouldGetGitConfigEvenWhenItsEmpty() throws URISyntaxException, IOException { + public void shouldGetGitConfigEvenWhenItsEmpty() throws URISyntaxException { when(repositoryHandler.getConfig()).thenReturn(null); MockHttpResponse response = get(); @@ -124,12 +151,84 @@ public class GitConfigResourceTest { @Test @SubjectAware(username = "readOnly") - public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException, IOException { + public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException { thrown.expectMessage("Subject does not have permission [configuration:write:git]"); put(); } + @Test + @SubjectAware(username = "writeOnly") + public void shouldReadDefaultRepositoryConfig() throws URISyntaxException { + when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X")); + + MockHttpRequest request = MockHttpRequest.get("/" + GitConfigResource.GIT_CONFIG_PATH_V2 + "/space/X"); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + assertThat(response.getContentAsString()) + .contains("\"defaultBranch\":null") + .contains("self") + .contains("update"); + } + + @Test + @SubjectAware(username = "readOnly") + public void shouldNotHaveUpdateLinkForReadOnlyUser() throws URISyntaxException { + when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X")); + + MockHttpRequest request = MockHttpRequest.get("/" + GitConfigResource.GIT_CONFIG_PATH_V2 + "/space/X"); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + assertThat(response.getContentAsString()) + .contains("\"defaultBranch\":null") + .contains("self") + .doesNotContain("update"); + } + + @Test + @SubjectAware(username = "writeOnly") + public void shouldReadStoredRepositoryConfig() throws URISyntaxException { + when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X")); + GitRepositoryConfig gitRepositoryConfig = new GitRepositoryConfig(); + gitRepositoryConfig.setDefaultBranch("test"); + when(configurationStore.get()).thenReturn(gitRepositoryConfig); + + MockHttpRequest request = MockHttpRequest.get("/" + GitConfigResource.GIT_CONFIG_PATH_V2 + "/space/X"); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + assertThat(response.getContentAsString()) + .contains("\"defaultBranch\":\"test\""); + } + + @Test + @SubjectAware(username = "writeOnly") + public void shouldStoreChangedRepositoryConfig() throws URISyntaxException { + when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X")); + + MockHttpRequest request = MockHttpRequest + .put("/" + GitConfigResource.GIT_CONFIG_PATH_V2 + "/space/X") + .contentType(GitVndMediaType.GIT_REPOSITORY_CONFIG) + .content("{\"defaultBranch\": \"new\"}".getBytes()); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus()); + assertThat(configurationStoreCaptor.getValue()) + .isInstanceOfSatisfying(GitRepositoryConfig.class, x -> { }) + .extracting("defaultBranch") + .containsExactly("new"); + } + private MockHttpResponse get() throws URISyntaxException { MockHttpRequest request = MockHttpRequest.get("/" + GitConfigResource.GIT_CONFIG_PATH_V2); MockHttpResponse response = new MockHttpResponse(); @@ -153,6 +252,4 @@ public class GitConfigResourceTest { config.setDisabled(false); return config; } - } - diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitRepositoryConfigEnricherTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitRepositoryConfigEnricherTest.java new file mode 100644 index 0000000000..d2942d08a3 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/api/v2/resources/GitRepositoryConfigEnricherTest.java @@ -0,0 +1,152 @@ +package sonia.scm.api.v2.resources; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.io.Resources; +import com.google.inject.Provider; +import com.google.inject.util.Providers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import sonia.scm.repository.NamespaceAndName; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryManager; +import sonia.scm.repository.api.Command; +import sonia.scm.repository.api.RepositoryService; +import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.web.JsonEnricherContext; +import sonia.scm.web.VndMediaType; + +import javax.ws.rs.core.MediaType; +import java.io.IOException; +import java.net.URI; +import java.net.URL; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class GitRepositoryConfigEnricherTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + private GitRepositoryConfigEnricher linkEnricher; + private JsonNode rootNode; + @Mock + private RepositoryManager manager; + + @BeforeEach + void globalSetUp() { + ScmPathInfoStore pathInfoStore = new ScmPathInfoStore(); + pathInfoStore.set(() -> URI.create("/")); + Provider pathInfoStoreProvider = Providers.of(pathInfoStore); + + linkEnricher = new GitRepositoryConfigEnricher(pathInfoStoreProvider, objectMapper, manager); + } + + @Nested + class ForSingleRepository { + @BeforeEach + void setUp() throws IOException { + URL resource = Resources.getResource("sonia/scm/repository/repository-001.json"); + rootNode = objectMapper.readTree(resource); + + when(manager.get(new NamespaceAndName("scmadmin", "web-resources"))).thenReturn(new Repository("id", "git", "scmadmin", "web-resources")); + } + + @Test + void shouldEnrichGitRepositories() { + JsonEnricherContext context = new JsonEnricherContext( + URI.create("/"), + MediaType.valueOf(VndMediaType.REPOSITORY), + rootNode + ); + + linkEnricher.enrich(context); + + String configLink = context.getResponseEntity() + .get("_links") + .get("configuration") + .get("href") + .asText(); + + assertThat(configLink).isEqualTo("/v2/config/git/scmadmin/web-resources"); + } + + @Test + void shouldNotEnrichOtherRepositories() { + when(manager.get(new NamespaceAndName("scmadmin", "web-resources"))).thenReturn(new Repository("id", "hg", "scmadmin", "web-resources")); + + JsonEnricherContext context = new JsonEnricherContext( + URI.create("/"), + MediaType.valueOf(VndMediaType.REPOSITORY), + rootNode + ); + + linkEnricher.enrich(context); + + JsonNode configLink = context.getResponseEntity() + .get("_links") + .get("configuration"); + + assertThat(configLink).isNull(); + } + } + + @Nested + class ForRepositoryCollection { + @BeforeEach + void setUp() throws IOException { + URL resource = Resources.getResource("sonia/scm/repository/repository-collection-001.json"); + rootNode = objectMapper.readTree(resource); + + when(manager.get(new NamespaceAndName("scmadmin", "web-resources"))).thenReturn(new Repository("id", "git", "scmadmin", "web-resources")); + } + + @Test + void shouldEnrichAllRepositories() { + JsonEnricherContext context = new JsonEnricherContext( + URI.create("/"), + MediaType.valueOf(VndMediaType.REPOSITORY_COLLECTION), + rootNode + ); + + linkEnricher.enrich(context); + + context.getResponseEntity() + .get("_embedded") + .withArray("repositories") + .elements() + .forEachRemaining(node -> { + String configLink = node + .get("_links") + .get("configuration") + .get("href") + .asText(); + + assertThat(configLink).isEqualTo("/v2/config/git/scmadmin/web-resources"); + }); + } + } + + @Test + void shouldNotModifyObjectsWithUnsupportedMediaType() throws IOException { + URL resource = Resources.getResource("sonia/scm/repository/repository-001.json"); + rootNode = objectMapper.readTree(resource); + JsonEnricherContext context = new JsonEnricherContext( + URI.create("/"), + MediaType.valueOf(VndMediaType.USER), + rootNode + ); + + linkEnricher.enrich(context); + + boolean hasNewPullRequestLink = context.getResponseEntity() + .get("_links") + .has("configuration"); + + assertThat(hasNewPullRequestLink).isFalse(); + } +} diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitHeadModifierTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitHeadModifierTest.java new file mode 100644 index 0000000000..23b3110567 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitHeadModifierTest.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2014, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ +package sonia.scm.repository; + +import com.google.common.base.Charsets; +import com.google.common.io.Files; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.io.File; +import java.io.IOException; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class GitHeadModifierTest { + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Mock + private GitRepositoryHandler repositoryHandler; + + @InjectMocks + private GitHeadModifier modifier; + + @Test + public void testEnsure() throws IOException, GitAPIException { + Repository repository = RepositoryTestData.createHeartOfGold("git"); + File headFile = create(repository, "master"); + + boolean result = modifier.ensure(repository, "develop"); + + assertEquals("ref: refs/heads/develop", Files.readFirstLine(headFile, Charsets.UTF_8)); + assertTrue(result); + } + + @Test + public void testEnsureWithSameBranch() throws IOException, GitAPIException { + Repository repository = RepositoryTestData.createHeartOfGold("git"); + create(repository, "develop"); + + boolean result = modifier.ensure(repository, "develop"); + + assertFalse(result); + } + + private File create(Repository repository, String head) throws IOException, GitAPIException { + File directory = temporaryFolder.newFolder(); + + Git.init() + .setBare(true) + .setDirectory(directory) + .call(); + + File headFile = new File(directory, "HEAD"); + Files.write(String.format("ref: refs/heads/%s\n", head), headFile, Charsets.UTF_8); + + when(repositoryHandler.getDirectory(repository.getId())).thenReturn(directory); + + return headFile; + } + +} diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java index dbd67a7f8e..cb10e15271 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryHandlerTest.java @@ -53,7 +53,7 @@ import static org.mockito.Mockito.when; /** * @author Sebastian Sdorra */ -@RunWith(MockitoJUnitRunner.class) +@RunWith(MockitoJUnitRunner.Silent.class) public class GitRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase { @Mock diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryModifyListenerTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryModifyListenerTest.java deleted file mode 100644 index a542674484..0000000000 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/GitRepositoryModifyListenerTest.java +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Copyright (c) 2014, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - -package sonia.scm.repository; - -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.Before; -import sonia.scm.HandlerEventType; - -/** - * Unit tests for {@link GitRepositoryModifyListener}. - * - * @author Sebastian Sdorra - */ -public class GitRepositoryModifyListenerTest { - - private GitRepositoryModifyTestListener repositoryModifyListener; - - /** - * Set up test object. - */ - @Before - public void setUpObjectUnderTest(){ - repositoryModifyListener = new GitRepositoryModifyTestListener(); - } - - /** - * Tests happy path. - */ - @Test - public void testHandleEvent() { - Repository old = RepositoryTestData.createHeartOfGold("git"); - old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master"); - Repository current = RepositoryTestData.createHeartOfGold("git"); - current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop"); - - RepositoryModificationEvent event = new RepositoryModificationEvent(HandlerEventType.MODIFY, current, old); - repositoryModifyListener.handleEvent(event); - - assertNotNull(repositoryModifyListener.repository); - assertSame(current, repositoryModifyListener.repository); - } - - /** - * Tests with new default branch. - */ - @Test - public void testWithNewDefaultBranch() { - Repository old = RepositoryTestData.createHeartOfGold("git"); - Repository current = RepositoryTestData.createHeartOfGold("git"); - current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop"); - - RepositoryModificationEvent event = new RepositoryModificationEvent(HandlerEventType.MODIFY, current, old); - repositoryModifyListener.handleEvent(event); - - assertNotNull(repositoryModifyListener.repository); - assertSame(current, repositoryModifyListener.repository); - } - - /** - * Tests with non git repositories. - */ - @Test - public void testNonGitRepository(){ - Repository old = RepositoryTestData.createHeartOfGold("hg"); - old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master"); - Repository current = RepositoryTestData.createHeartOfGold("hg"); - current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop"); - - RepositoryModificationEvent event = new RepositoryModificationEvent(HandlerEventType.MODIFY, current, old); - repositoryModifyListener.handleEvent(event); - - assertNull(repositoryModifyListener.repository); - } - - /** - * Tests without default branch. - */ - @Test - public void testWithoutDefaultBranch(){ - Repository old = RepositoryTestData.createHeartOfGold("git"); - Repository current = RepositoryTestData.createHeartOfGold("git"); - - RepositoryModificationEvent event = new RepositoryModificationEvent(HandlerEventType.MODIFY, current, old); - repositoryModifyListener.handleEvent(event); - - assertNull(repositoryModifyListener.repository); - } - - /** - * Tests with non modify event. - */ - @Test - public void testNonModifyEvent(){ - Repository old = RepositoryTestData.createHeartOfGold("git"); - old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master"); - Repository current = RepositoryTestData.createHeartOfGold("git"); - current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop"); - - RepositoryModificationEvent event = new RepositoryModificationEvent(HandlerEventType.CREATE, current, old); - repositoryModifyListener.handleEvent(event); - - assertNull(repositoryModifyListener.repository); - } - - /** - * Tests with non git repositories. - */ - @Test - public void testNoModification(){ - Repository old = RepositoryTestData.createHeartOfGold("git"); - old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master"); - Repository current = RepositoryTestData.createHeartOfGold("git"); - current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master"); - - RepositoryModificationEvent event = new RepositoryModificationEvent(HandlerEventType.MODIFY, current, old); - repositoryModifyListener.handleEvent(event); - - assertNull(repositoryModifyListener.repository); - } - - private static class GitRepositoryModifyTestListener extends GitRepositoryModifyListener { - - private Repository repository; - - @Override - protected void sendClearRepositoryCacheEvent(Repository repository) { - this.repository = repository; - } - - } - - -} \ No newline at end of file diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractGitCommandTestBase.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractGitCommandTestBase.java index 0b3c1d6e9d..630236b20b 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractGitCommandTestBase.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/AbstractGitCommandTestBase.java @@ -35,6 +35,11 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import org.junit.After; +import org.junit.Before; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; +import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.store.InMemoryConfigurationStore; +import sonia.scm.store.InMemoryConfigurationStoreFactory; /** * @@ -51,6 +56,7 @@ public class AbstractGitCommandTestBase extends ZippedRepositoryTestBase public void close() { if (context != null) { + context.setConfig(new GitRepositoryConfig()); context.close(); } } @@ -65,7 +71,7 @@ public class AbstractGitCommandTestBase extends ZippedRepositoryTestBase { if (context == null) { - context = new GitContext(repositoryDirectory, repository); + context = new GitContext(repositoryDirectory, repository, new GitRepositoryConfigStoreProvider(InMemoryConfigurationStoreFactory.create())); } return context; diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBlameCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBlameCommandTest.java index 5757cd5d5e..817e4641dd 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBlameCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBlameCommandTest.java @@ -35,9 +35,11 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import org.junit.Test; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.repository.BlameLine; import sonia.scm.repository.BlameResult; -import sonia.scm.repository.GitConstants; +import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.store.InMemoryConfigurationStoreFactory; import java.io.IOException; @@ -73,7 +75,7 @@ public class GitBlameCommandTest extends AbstractGitCommandTestBase assertEquals("fcd0ef1831e4002ac43ea539f4094334c79ea9ec", result.getLine(1).getRevision()); // set default branch and test again - repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch"); + createContext().setConfig(new GitRepositoryConfig("test-branch")); result = createCommand().getBlameResult(request); assertNotNull(result); assertEquals(1, result.getTotal()); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java index 5e63adfb70..2ff3c73420 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitBrowseCommandTest.java @@ -32,9 +32,11 @@ package sonia.scm.repository.spi; import org.junit.Test; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.repository.BrowserResult; import sonia.scm.repository.FileObject; -import sonia.scm.repository.GitConstants; +import sonia.scm.repository.GitRepositoryConfig; +import sonia.scm.store.InMemoryConfigurationStoreFactory; import java.io.IOException; import java.util.Collection; @@ -78,7 +80,7 @@ public class GitBrowseCommandTest extends AbstractGitCommandTestBase { @Test public void testExplicitDefaultBranch() throws IOException { - repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch"); + createContext().setConfig(new GitRepositoryConfig("test-branch")); FileObject root = createCommand().getBrowserResult(new BrowseCommandRequest()).getFile(); assertNotNull(root); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitCatCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitCatCommandTest.java index 079fcac1da..0418bc3e61 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitCatCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitCatCommandTest.java @@ -38,7 +38,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import sonia.scm.NotFoundException; -import sonia.scm.repository.GitConstants; +import sonia.scm.repository.GitRepositoryConfig; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -67,7 +67,7 @@ public class GitCatCommandTest extends AbstractGitCommandTestBase { assertEquals("a\nline for blame", execute(request)); // set default branch for repository and check again - repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch"); + createContext().setConfig(new GitRepositoryConfig("test-branch")); assertEquals("a and b", execute(request)); } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java index acf0b0f820..376d7cdf7a 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java @@ -38,7 +38,9 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Ignore; import org.junit.Test; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.repository.ChangesetPagingResult; +import sonia.scm.store.InMemoryConfigurationStoreFactory; import java.io.IOException; @@ -103,7 +105,7 @@ public class GitIncomingCommandTest commit(outgoing, "added a"); - GitPullCommand pull = new GitPullCommand(handler, new GitContext(incomingDirectory, null), incomingRepository); + GitPullCommand pull = new GitPullCommand(handler, new GitContext(incomingDirectory, null, new GitRepositoryConfigStoreProvider(new InMemoryConfigurationStoreFactory())), incomingRepository); PullCommandRequest req = new PullCommandRequest(); req.setRemoteRepository(outgoingRepository); pull.pull(req); @@ -187,7 +189,7 @@ public class GitIncomingCommandTest */ private GitIncomingCommand createCommand() { - return new GitIncomingCommand(handler, new GitContext(incomingDirectory, null), + return new GitIncomingCommand(handler, new GitContext(incomingDirectory, null, new GitRepositoryConfigStoreProvider(new InMemoryConfigurationStoreFactory())), incomingRepository); } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandAncestorTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandAncestorTest.java new file mode 100644 index 0000000000..d36922f941 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandAncestorTest.java @@ -0,0 +1,102 @@ + +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository.spi; + +import org.junit.Test; +import sonia.scm.repository.ChangesetPagingResult; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Unit tests for {@link GitLogCommand} with an ancestor commit. This test uses the following git repository: + * + *
+ * * 86e9ca0 (HEAD -> b) b5
+ * *   d69edb3 Merge branch 'master' into b
+ * |\
+ * | * 946a8db (master) f
+ * | * b19b9cc e
+ * * | 3d6109c b4
+ * * | 6330653 b3
+ * * |   a49a28e Merge branch 'master' into b
+ * |\ \
+ * | |/
+ * | * 0235584 d
+ * | * 20251c5 c
+ * * | 5023b85 b2
+ * * | 201ecc1 b1
+ * |/
+ * * 36b19e4 b
+ * * c2190a9 a
+ * 
+ * @author Sebastian Sdorra + */ +public class GitLogCommandAncestorTest extends AbstractGitCommandTestBase +{ + @Override + protected String getZippedRepositoryResource() + { + return "sonia/scm/repository/spi/scm-git-ancestor-test.zip"; + } + + @Test + public void testGetAncestor() + { + LogCommandRequest request = new LogCommandRequest(); + + request.setBranch("b"); + request.setAncestorChangeset("master"); + + ChangesetPagingResult result = createCommand().getChangesets(request); + + assertNotNull(result); + assertEquals(7, result.getTotal()); + assertEquals(7, result.getChangesets().size()); + + assertEquals("86e9ca012202b36865373a63c12ef4f4353506cd", result.getChangesets().get(0).getId()); + assertEquals("d69edb314d07ab20ad626e3101597702d3510b5d", result.getChangesets().get(1).getId()); + assertEquals("3d6109c4c830e91eaf12ac6a331a5fccd670fe3c", result.getChangesets().get(2).getId()); + assertEquals("63306538d06924d6b254f86541c638021c001141", result.getChangesets().get(3).getId()); + assertEquals("a49a28e0beb0ab55f985598d05b8628c2231c9b6", result.getChangesets().get(4).getId()); + assertEquals("5023b850c2077db857593a3c0269329c254a370d", result.getChangesets().get(5).getId()); + assertEquals("201ecc1131e6b99fb0a0fe9dcbc8c044383e1a07", result.getChangesets().get(6).getId()); + } + + private GitLogCommand createCommand() + { + return new GitLogCommand(createContext(), repository); + } +} diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java index 4afaf09c67..e2ab85d9a7 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java @@ -36,9 +36,11 @@ package sonia.scm.repository.spi; import com.google.common.io.Files; import org.junit.Test; +import sonia.scm.event.ScmEventBus; import sonia.scm.repository.Changeset; import sonia.scm.repository.ChangesetPagingResult; -import sonia.scm.repository.GitConstants; +import sonia.scm.repository.ClearRepositoryCacheEvent; +import sonia.scm.repository.GitRepositoryConfig; import sonia.scm.repository.Modifications; import java.io.File; @@ -78,7 +80,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase assertTrue(result.getChangesets().stream().allMatch(r -> r.getBranches().isEmpty())); // set default branch and fetch again - repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch"); + createContext().setConfig(new GitRepositoryConfig("test-branch")); result = createCommand().getChangesets(new LogCommandRequest()); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModificationsCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModificationsCommandTest.java index 41a516a124..dbb510fb7e 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModificationsCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitModificationsCommandTest.java @@ -18,8 +18,8 @@ public class GitModificationsCommandTest extends AbstractRemoteCommandTestBase { @Before public void init() { - incomingModificationsCommand = new GitModificationsCommand(new GitContext(incomingDirectory, null), incomingRepository); - outgoingModificationsCommand = new GitModificationsCommand(new GitContext(outgoingDirectory, null), outgoingRepository); + incomingModificationsCommand = new GitModificationsCommand(new GitContext(incomingDirectory, null, null), incomingRepository); + outgoingModificationsCommand = new GitModificationsCommand(new GitContext(outgoingDirectory, null, null), outgoingRepository); } @Test @@ -63,12 +63,12 @@ public class GitModificationsCommandTest extends AbstractRemoteCommandTestBase { } void pushOutgoingAndPullIncoming() throws IOException { - GitPushCommand cmd = new GitPushCommand(handler, new GitContext(outgoingDirectory, null), + GitPushCommand cmd = new GitPushCommand(handler, new GitContext(outgoingDirectory, null, null), outgoingRepository); PushCommandRequest request = new PushCommandRequest(); request.setRemoteRepository(incomingRepository); cmd.push(request); - GitPullCommand pullCommand = new GitPullCommand(handler, new GitContext(incomingDirectory, null), + GitPullCommand pullCommand = new GitPullCommand(handler, new GitContext(incomingDirectory, null, null), incomingRepository); PullCommandRequest pullRequest = new PullCommandRequest(); pullRequest.setRemoteRepository(incomingRepository); diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java index 65592cf7e4..2525a6fa38 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java @@ -38,7 +38,9 @@ package sonia.scm.repository.spi; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Test; +import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.repository.ChangesetPagingResult; +import sonia.scm.store.InMemoryConfigurationStoreFactory; import java.io.IOException; @@ -104,7 +106,7 @@ public class GitOutgoingCommandTest extends AbstractRemoteCommandTestBase commit(outgoing, "added a"); GitPushCommand push = new GitPushCommand(handler, - new GitContext(outgoingDirectory, null), + new GitContext(outgoingDirectory, null, null), outgoingRepository); PushCommandRequest req = new PushCommandRequest(); @@ -158,7 +160,7 @@ public class GitOutgoingCommandTest extends AbstractRemoteCommandTestBase */ private GitOutgoingCommand createCommand() { - return new GitOutgoingCommand(handler, new GitContext(outgoingDirectory, null), + return new GitOutgoingCommand(handler, new GitContext(outgoingDirectory, null, new GitRepositoryConfigStoreProvider(new InMemoryConfigurationStoreFactory())), outgoingRepository); } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitPushCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitPushCommandTest.java index 70212ba233..6aa831ec60 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitPushCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitPushCommandTest.java @@ -98,7 +98,7 @@ public class GitPushCommandTest extends AbstractRemoteCommandTestBase */ private GitPushCommand createCommand() { - return new GitPushCommand(handler, new GitContext(outgoingDirectory, null), + return new GitPushCommand(handler, new GitContext(outgoingDirectory, null, null), outgoingRepository); } } diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/configuration/shiro.ini b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/configuration/shiro.ini index 5d30a000f2..8a8ff98c2f 100644 --- a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/configuration/shiro.ini +++ b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/configuration/shiro.ini @@ -1,6 +1,6 @@ [users] -readOnly = secret, reader -writeOnly = secret, writer +readOnly = secret, reader, repoRead +writeOnly = secret, writer, repoWrite readWrite = secret, readerWriter admin = secret, admin @@ -9,3 +9,5 @@ reader = configuration:read:git writer = configuration:write:git readerWriter = configuration:*:git admin = * +repoRead = repository:read:* +repoWrite = repository:modify:* diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/repository-001.json b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/repository-001.json new file mode 100644 index 0000000000..43ea136942 --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/repository-001.json @@ -0,0 +1,42 @@ +{ + "creationDate": "2018-11-09T09:48:32.732Z", + "description": "Handling static webresources made easy", + "healthCheckFailures": [], + "lastModified": "2018-11-09T09:49:20.973Z", + "namespace": "scmadmin", + "name": "web-resources", + "archived": false, + "type": "git", + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "delete": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "update": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "permissions": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/" + }, + "protocol": [ + { + "href": "http://localhost:8081/scm/repo/scmadmin/web-resources", + "name": "http" + } + ], + "tags": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/" + }, + "branches": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/" + }, + "changesets": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/" + }, + "sources": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/" + } + } +} diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/repository-collection-001.json b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/repository-collection-001.json new file mode 100644 index 0000000000..f4eeb24bbc --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/repository-collection-001.json @@ -0,0 +1,106 @@ +{ + "page": 0, + "pageTotal": 1, + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10" + }, + "first": { + "href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10" + }, + "last": { + "href": "http://localhost:8081/scm/api/v2/repositories/?page=0&pageSize=10" + }, + "create": { + "href": "http://localhost:8081/scm/api/v2/repositories/" + } + }, + "_embedded": { + "repositories": [ + { + "creationDate": "2018-11-09T09:48:32.732Z", + "description": "Handling static webresources made easy", + "healthCheckFailures": [], + "lastModified": "2018-11-09T09:49:20.973Z", + "namespace": "scmadmin", + "name": "web-resources", + "archived": false, + "type": "git", + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "delete": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "update": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "permissions": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/" + }, + "protocol": [ + { + "href": "http://localhost:8081/scm/repo/scmadmin/web-resources", + "name": "http" + } + ], + "tags": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/" + }, + "branches": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/" + }, + "changesets": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/" + }, + "sources": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/" + } + } + }, + { + "creationDate": "2018-11-09T09:48:32.732Z", + "description": "Handling static webresources made easy", + "healthCheckFailures": [], + "lastModified": "2018-11-09T09:49:20.973Z", + "namespace": "scmadmin", + "name": "web-resources", + "archived": false, + "type": "git", + "_links": { + "self": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "delete": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "update": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources" + }, + "permissions": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/permissions/" + }, + "protocol": [ + { + "href": "http://localhost:8081/scm/repo/scmadmin/web-resources", + "name": "http" + } + ], + "tags": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/tags/" + }, + "branches": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/branches/" + }, + "changesets": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/changesets/" + }, + "sources": { + "href": "http://localhost:8081/scm/api/v2/repositories/scmadmin/web-resources/sources/" + } + } + } + ] + } +} diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-ancestor-test.zip b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-ancestor-test.zip new file mode 100644 index 0000000000..d740de7674 Binary files /dev/null and b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-ancestor-test.zip differ diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java index 2c5641bfd1..ee21703c4a 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java @@ -37,13 +37,31 @@ package sonia.scm.store; /** * In memory configuration store factory for testing purposes. + * + * Use {@link #create()} to get a store that creates the same store on each request. * * @author Sebastian Sdorra */ public class InMemoryConfigurationStoreFactory implements ConfigurationStoreFactory { + private ConfigurationStore store; + + public static ConfigurationStoreFactory create() { + return new InMemoryConfigurationStoreFactory(new InMemoryConfigurationStore()); + } + + public InMemoryConfigurationStoreFactory() { + } + + public InMemoryConfigurationStoreFactory(ConfigurationStore store) { + this.store = store; + } + @Override public ConfigurationStore getStore(TypedStoreParameters storeParameters) { + if (store != null) { + return store; + } return new InMemoryConfigurationStore<>(); } } diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryDataStore.java b/scm-test/src/main/java/sonia/scm/store/InMemoryDataStore.java new file mode 100644 index 0000000000..06198d89bf --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryDataStore.java @@ -0,0 +1,53 @@ +package sonia.scm.store; + +import sonia.scm.security.KeyGenerator; +import sonia.scm.security.UUIDKeyGenerator; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * In memory store implementation of {@link DataStore}. + * + * @author Sebastian Sdorra + * + * @param type of stored object + */ +public class InMemoryDataStore implements DataStore { + + private final Map store = new HashMap<>(); + private KeyGenerator generator = new UUIDKeyGenerator(); + + @Override + public String put(T item) { + String key = generator.createKey(); + store.put(key, item); + return key; + } + + @Override + public void put(String id, T item) { + store.put(id, item); + } + + @Override + public Map getAll() { + return Collections.unmodifiableMap(store); + } + + @Override + public void clear() { + store.clear(); + } + + @Override + public void remove(String id) { + store.remove(id); + } + + @Override + public T get(String id) { + return store.get(id); + } +} diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryDataStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryDataStoreFactory.java new file mode 100644 index 0000000000..b0e95e9f9c --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryDataStoreFactory.java @@ -0,0 +1,26 @@ +package sonia.scm.store; + +/** + * In memory configuration store factory for testing purposes. + * + * @author Sebastian Sdorra + */ +public class InMemoryDataStoreFactory implements DataStoreFactory { + + private InMemoryDataStore store; + + public InMemoryDataStoreFactory() { + } + + public InMemoryDataStoreFactory(InMemoryDataStore store) { + this.store = store; + } + + @Override + public DataStore getStore(TypedStoreParameters storeParameters) { + if (store != null) { + return store; + } + return new InMemoryDataStore<>(); + } +} diff --git a/scm-ui/src/repos/containers/BranchSelector.js b/scm-ui-components/packages/ui-components/src/BranchSelector.js similarity index 65% rename from scm-ui/src/repos/containers/BranchSelector.js rename to scm-ui-components/packages/ui-components/src/BranchSelector.js index ced1cb8f44..d03011bfdd 100644 --- a/scm-ui/src/repos/containers/BranchSelector.js +++ b/scm-ui-components/packages/ui-components/src/BranchSelector.js @@ -1,12 +1,10 @@ // @flow import React from "react"; -import type { Branch } from "@scm-manager/ui-types"; -import DropDown from "../components/DropDown"; -import { translate } from "react-i18next"; +import type {Branch} from "@scm-manager/ui-types"; import injectSheet from "react-jss"; -import { compose } from "redux"; import classNames from "classnames"; +import DropDown from "./forms/DropDown"; const styles = { zeroflex: { @@ -14,17 +12,22 @@ const styles = { }, minWidthOfLabel: { minWidth: "4.5rem" + }, + wrapper: { + padding: "1rem 1.5rem 0.25rem 1.5rem", + border: "1px solid #eee", + borderRadius: "5px 5px 0 0" } }; type Props = { branches: Branch[], // TODO: Use generics? selected: (branch?: Branch) => void, - selectedBranch: string, + selectedBranch?: string, + label: string, // context props - classes: Object, - t: string => string + classes: Object }; type State = { selectedBranch?: Branch }; @@ -36,17 +39,22 @@ class BranchSelector extends React.Component { } componentDidMount() { - this.props.branches - .filter(branch => branch.name === this.props.selectedBranch) - .forEach(branch => this.setState({ selectedBranch: branch })); + const selectedBranch = this.props.branches.find(branch => branch.name === this.props.selectedBranch); + this.setState({ selectedBranch }); } render() { - const { branches, classes, t } = this.props; + const { branches, classes, label } = this.props; if (branches) { return ( -
+
{ classes.minWidthOfLabel )} > - +
@@ -82,6 +90,12 @@ class BranchSelector extends React.Component { branchSelected = (branchName: string) => { const { branches, selected } = this.props; + + if (!branchName) { + this.setState({ selectedBranch: undefined }); + selected(undefined); + return; + } const branch = branches.find(b => b.name === branchName); selected(branch); @@ -89,7 +103,4 @@ class BranchSelector extends React.Component { }; } -export default compose( - injectSheet(styles), - translate("repos") -)(BranchSelector); +export default injectSheet(styles)(BranchSelector); diff --git a/scm-ui-components/packages/ui-components/src/ErrorNotification.js b/scm-ui-components/packages/ui-components/src/ErrorNotification.js index 5600d81799..6645db5f60 100644 --- a/scm-ui-components/packages/ui-components/src/ErrorNotification.js +++ b/scm-ui-components/packages/ui-components/src/ErrorNotification.js @@ -2,6 +2,7 @@ import React from "react"; import { translate } from "react-i18next"; import Notification from "./Notification"; +import {UNAUTHORIZED_ERROR} from "./apiclient"; type Props = { t: string => string, @@ -9,14 +10,25 @@ type Props = { }; class ErrorNotification extends React.Component { + render() { const { t, error } = this.props; if (error) { - return ( - - {t("error-notification.prefix")}: {error.message} - - ); + if (error === UNAUTHORIZED_ERROR) { + return ( + + {t("error-notification.prefix")}: {t("error-notification.timeout")} + {" "} + {t("error-notification.loginLink")} + + ); + } else { + return ( + + {t("error-notification.prefix")}: {error.message} + + ); + } } return null; } diff --git a/scm-ui-components/packages/ui-components/src/HelpIcon.js b/scm-ui-components/packages/ui-components/src/HelpIcon.js index fba8ead422..9e095bd8a7 100644 --- a/scm-ui-components/packages/ui-components/src/HelpIcon.js +++ b/scm-ui-components/packages/ui-components/src/HelpIcon.js @@ -1,14 +1,23 @@ //@flow import React from "react"; +import injectSheet from "react-jss"; import classNames from "classnames"; type Props = { + classes: any +}; + +const styles = { + textinfo: { + color: "#98d8f3 !important" + } }; class HelpIcon extends React.Component { render() { - return + const { classes } = this.props; + return ; } } -export default HelpIcon; +export default injectSheet(styles)(HelpIcon); diff --git a/scm-ui-components/packages/ui-components/src/buttons/AddButton.js b/scm-ui-components/packages/ui-components/src/buttons/AddButton.js index de72bdaab9..8f46fb66a4 100644 --- a/scm-ui-components/packages/ui-components/src/buttons/AddButton.js +++ b/scm-ui-components/packages/ui-components/src/buttons/AddButton.js @@ -1,11 +1,11 @@ -//@flow -import React from "react"; -import Button, { type ButtonProps } from "./Button"; - -class AddButton extends React.Component { - render() { - return
); } diff --git a/scm-ui/src/config/components/form/LoginAttempt.js b/scm-ui/src/config/components/form/LoginAttempt.js index ca16761ba7..b0ca580283 100644 --- a/scm-ui/src/config/components/form/LoginAttempt.js +++ b/scm-ui/src/config/components/form/LoginAttempt.js @@ -40,24 +40,30 @@ class LoginAttempt extends React.Component { return (
- - +
+
+ +
+
+ +
+
); } diff --git a/scm-ui/src/config/components/form/ProxySettings.js b/scm-ui/src/config/components/form/ProxySettings.js index 7656bc270c..ed92d74b12 100644 --- a/scm-ui/src/config/components/form/ProxySettings.js +++ b/scm-ui/src/config/components/form/ProxySettings.js @@ -37,56 +37,76 @@ class ProxySettings extends React.Component { return (
- - - - - - - this.props.onChange(isValid, changedValue, name) - } - disabled={!enableProxy || !hasUpdatePermission} - /> - +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + this.props.onChange(isValid, changedValue, name) + } + disabled={!enableProxy || !hasUpdatePermission} + /> + +
+
); } diff --git a/scm-ui/src/config/containers/Config.js b/scm-ui/src/config/containers/Config.js index 6d935fe33a..60dc9bb75f 100644 --- a/scm-ui/src/config/containers/Config.js +++ b/scm-ui/src/config/containers/Config.js @@ -1,86 +1,86 @@ -// @flow -import React from "react"; -import { translate } from "react-i18next"; -import { Route } from "react-router"; -import { ExtensionPoint } from "@scm-manager/ui-extensions"; - -import type { Links } from "@scm-manager/ui-types"; -import { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components"; -import GlobalConfig from "./GlobalConfig"; -import type { History } from "history"; -import {connect} from "react-redux"; -import {compose} from "redux"; -import { getLinks } from "../../modules/indexResource"; - -type Props = { - links: Links, - - // context objects - t: string => string, - match: any, - history: History -}; - -class Config extends React.Component { - stripEndingSlash = (url: string) => { - if (url.endsWith("/")) { - return url.substring(0, url.length - 2); - } - return url; - }; - - matchedUrl = () => { - return this.stripEndingSlash(this.props.match.url); - }; - - render() { - const { links, t } = this.props; - - const url = this.matchedUrl(); - const extensionProps = { - links, - url - }; - - return ( - -
-
- - -
-
- -
- - -
-
-
-
-
- ); - } -} - -const mapStateToProps = (state: any) => { - const links = getLinks(state); - return { - links - }; -}; - -export default compose( - connect(mapStateToProps), - translate("config") -)(Config); - +// @flow +import React from "react"; +import { translate } from "react-i18next"; +import { Route } from "react-router"; +import { ExtensionPoint } from "@scm-manager/ui-extensions"; + +import type { Links } from "@scm-manager/ui-types"; +import { Page, Navigation, NavLink, Section } from "@scm-manager/ui-components"; +import GlobalConfig from "./GlobalConfig"; +import type { History } from "history"; +import {connect} from "react-redux"; +import {compose} from "redux"; +import { getLinks } from "../../modules/indexResource"; + +type Props = { + links: Links, + + // context objects + t: string => string, + match: any, + history: History +}; + +class Config extends React.Component { + stripEndingSlash = (url: string) => { + if (url.endsWith("/")) { + return url.substring(0, url.length - 2); + } + return url; + }; + + matchedUrl = () => { + return this.stripEndingSlash(this.props.match.url); + }; + + render() { + const { links, t } = this.props; + + const url = this.matchedUrl(); + const extensionProps = { + links, + url + }; + + return ( + +
+
+ + +
+
+ +
+ + +
+
+
+
+
+ ); + } +} + +const mapStateToProps = (state: any) => { + const links = getLinks(state); + return { + links + }; +}; + +export default compose( + connect(mapStateToProps), + translate("config") +)(Config); + diff --git a/scm-ui/src/config/modules/config.js b/scm-ui/src/config/modules/config.js index 352afefb70..2d14fcfea6 100644 --- a/scm-ui/src/config/modules/config.js +++ b/scm-ui/src/config/modules/config.js @@ -32,9 +32,8 @@ export function fetchConfig(link: string) { .then(data => { dispatch(fetchConfigSuccess(data)); }) - .catch(cause => { - const error = new Error(`could not fetch config: ${cause.message}`); - dispatch(fetchConfigFailure(error)); + .catch(err => { + dispatch(fetchConfigFailure(err)); }); }; } @@ -73,13 +72,8 @@ export function modifyConfig(config: Config, callback?: () => void) { callback(); } }) - .catch(cause => { - dispatch( - modifyConfigFailure( - config, - new Error(`could not modify config: ${cause.message}`) - ) - ); + .catch(err => { + dispatch(modifyConfigFailure(config, err)); }); }; } diff --git a/scm-ui/src/containers/ProfileInfo.js b/scm-ui/src/containers/ProfileInfo.js index 7adc3065b7..9c4a5a9323 100644 --- a/scm-ui/src/containers/ProfileInfo.js +++ b/scm-ui/src/containers/ProfileInfo.js @@ -1,53 +1,53 @@ -// @flow -import React from "react"; -import type { Me } from "@scm-manager/ui-types"; -import { MailLink, AvatarWrapper, AvatarImage } from "@scm-manager/ui-components"; -import { compose } from "redux"; -import { translate } from "react-i18next"; - -type Props = { - me: Me, - - // Context props - t: string => string -}; -type State = {}; - -class ProfileInfo extends React.Component { - render() { - const { me, t } = this.props; - return ( -
- -
-

- -

-
-
-
- - - - - - - - - - - - - - - -
{t("profile.username")}{me.name}
{t("profile.displayName")}{me.displayName}
{t("profile.mail")} - -
-
-
- ); - } -} - -export default compose(translate("commons"))(ProfileInfo); +// @flow +import React from "react"; +import type { Me } from "@scm-manager/ui-types"; +import { MailLink, AvatarWrapper, AvatarImage } from "@scm-manager/ui-components"; +import { compose } from "redux"; +import { translate } from "react-i18next"; + +type Props = { + me: Me, + + // Context props + t: string => string +}; +type State = {}; + +class ProfileInfo extends React.Component { + render() { + const { me, t } = this.props; + return ( +
+ +
+

+ +

+
+
+
+ + + + + + + + + + + + + + + +
{t("profile.username")}{me.name}
{t("profile.displayName")}{me.displayName}
{t("profile.mail")} + +
+
+
+ ); + } +} + +export default compose(translate("commons"))(ProfileInfo); diff --git a/scm-ui/src/groups/components/table/Details.js b/scm-ui/src/groups/components/table/Details.js index 097822a1f3..eb4c3fa0d5 100644 --- a/scm-ui/src/groups/components/table/Details.js +++ b/scm-ui/src/groups/components/table/Details.js @@ -1,69 +1,69 @@ -//@flow -import React from "react"; -import type { Group } from "@scm-manager/ui-types"; -import { translate } from "react-i18next"; -import GroupMember from "./GroupMember"; -import { DateFromNow } from "@scm-manager/ui-components"; - -type Props = { - group: Group, - t: string => string -}; - -class Details extends React.Component { - render() { - const { group, t } = this.props; - return ( - - - - - - - - - - - - - - - - - - - - - - - {this.renderMembers()} - -
{t("group.name")}{group.name}
{t("group.description")}{group.description}
{t("group.type")}{group.type}
{t("group.creationDate")} - -
{t("group.lastModified")} - -
- ); - } - - renderMembers() { - if (this.props.group.members.length > 0) { - return ( - - - {this.props.t("group.members")} -
    - {this.props.group._embedded.members.map((member, index) => { - return ; - })} -
- - - ); - } else { - return; - } - } -} - -export default translate("groups")(Details); +//@flow +import React from "react"; +import type { Group } from "@scm-manager/ui-types"; +import { translate } from "react-i18next"; +import GroupMember from "./GroupMember"; +import { DateFromNow } from "@scm-manager/ui-components"; + +type Props = { + group: Group, + t: string => string +}; + +class Details extends React.Component { + render() { + const { group, t } = this.props; + return ( + + + + + + + + + + + + + + + + + + + + + + + {this.renderMembers()} + +
{t("group.name")}{group.name}
{t("group.description")}{group.description}
{t("group.type")}{group.type}
{t("group.creationDate")} + +
{t("group.lastModified")} + +
+ ); + } + + renderMembers() { + if (this.props.group.members.length > 0) { + return ( + + + {this.props.t("group.members")} +
    + {this.props.group._embedded.members.map((member, index) => { + return ; + })} +
+ + + ); + } else { + return; + } + } +} + +export default translate("groups")(Details); diff --git a/scm-ui/src/groups/components/table/GroupRow.js b/scm-ui/src/groups/components/table/GroupRow.js index 32a8f946df..ccff8bd193 100644 --- a/scm-ui/src/groups/components/table/GroupRow.js +++ b/scm-ui/src/groups/components/table/GroupRow.js @@ -1,25 +1,25 @@ -// @flow -import React from "react"; -import { Link } from "react-router-dom"; -import type { Group } from "@scm-manager/ui-types"; - -type Props = { - group: Group -}; - -export default class GroupRow extends React.Component { - renderLink(to: string, label: string) { - return {label}; - } - - render() { - const { group } = this.props; - const to = `/group/${group.name}`; - return ( - - {this.renderLink(to, group.name)} - {group.description} - - ); - } -} +// @flow +import React from "react"; +import { Link } from "react-router-dom"; +import type { Group } from "@scm-manager/ui-types"; + +type Props = { + group: Group +}; + +export default class GroupRow extends React.Component { + renderLink(to: string, label: string) { + return {label}; + } + + render() { + const { group } = this.props; + const to = `/group/${group.name}`; + return ( + + {this.renderLink(to, group.name)} + {group.description} + + ); + } +} diff --git a/scm-ui/src/groups/components/table/GroupTable.js b/scm-ui/src/groups/components/table/GroupTable.js index 30c8401d7d..cd38180fc4 100644 --- a/scm-ui/src/groups/components/table/GroupTable.js +++ b/scm-ui/src/groups/components/table/GroupTable.js @@ -1,33 +1,33 @@ -// @flow -import React from "react"; -import { translate } from "react-i18next"; -import GroupRow from "./GroupRow"; -import type { Group } from "@scm-manager/ui-types"; - -type Props = { - t: string => string, - groups: Group[] -}; - -class GroupTable extends React.Component { - render() { - const { groups, t } = this.props; - return ( - - - - - - - - - {groups.map((group, index) => { - return ; - })} - -
{t("group.name")}{t("group.description")}
- ); - } -} - -export default translate("groups")(GroupTable); +// @flow +import React from "react"; +import { translate } from "react-i18next"; +import GroupRow from "./GroupRow"; +import type { Group } from "@scm-manager/ui-types"; + +type Props = { + t: string => string, + groups: Group[] +}; + +class GroupTable extends React.Component { + render() { + const { groups, t } = this.props; + return ( + + + + + + + + + {groups.map((group, index) => { + return ; + })} + +
{t("group.name")}{t("group.description")}
+ ); + } +} + +export default translate("groups")(GroupTable); diff --git a/scm-ui/src/groups/modules/groups.js b/scm-ui/src/groups/modules/groups.js index 165648edaa..483b5b3798 100644 --- a/scm-ui/src/groups/modules/groups.js +++ b/scm-ui/src/groups/modules/groups.js @@ -54,9 +54,8 @@ export function fetchGroupsByLink(link: string) { .then(data => { dispatch(fetchGroupsSuccess(data)); }) - .catch(cause => { - const error = new Error(`could not fetch groups: ${cause.message}`); - dispatch(fetchGroupsFailure(link, error)); + .catch(err => { + dispatch(fetchGroupsFailure(link, err)); }); }; } @@ -105,9 +104,8 @@ function fetchGroup(link: string, name: string) { .then(data => { dispatch(fetchGroupSuccess(data)); }) - .catch(cause => { - const error = new Error(`could not fetch group: ${cause.message}`); - dispatch(fetchGroupFailure(name, error)); + .catch(err => { + dispatch(fetchGroupFailure(name, err)); }); }; } @@ -151,10 +149,10 @@ export function createGroup(link: string, group: Group, callback?: () => void) { callback(); } }) - .catch(error => { + .catch(err => { dispatch( createGroupFailure( - new Error(`Failed to create group ${group.name}: ${error.message}`) + err ) ); }); @@ -201,11 +199,11 @@ export function modifyGroup(group: Group, callback?: () => void) { .then(() => { dispatch(fetchGroupByLink(group)); }) - .catch(cause => { + .catch(err => { dispatch( modifyGroupFailure( group, - new Error(`could not modify group ${group.name}: ${cause.message}`) + err ) ); }); @@ -259,11 +257,8 @@ export function deleteGroup(group: Group, callback?: () => void) { callback(); } }) - .catch(cause => { - const error = new Error( - `could not delete group ${group.name}: ${cause.message}` - ); - dispatch(deleteGroupFailure(group, error)); + .catch(err => { + dispatch(deleteGroupFailure(group, err)); }); }; } diff --git a/scm-ui/src/repos/components/RepositoryDetailTable.js b/scm-ui/src/repos/components/RepositoryDetailTable.js index db5f9abbc1..ca63398670 100644 --- a/scm-ui/src/repos/components/RepositoryDetailTable.js +++ b/scm-ui/src/repos/components/RepositoryDetailTable.js @@ -1,55 +1,55 @@ -//@flow -import React from "react"; -import type { Repository } from "@scm-manager/ui-types"; -import { MailLink, DateFromNow } from "@scm-manager/ui-components"; -import { translate } from "react-i18next"; - -type Props = { - repository: Repository, - // context props - t: string => string -}; - -class RepositoryDetailTable extends React.Component { - render() { - const { repository, t } = this.props; - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{t("repository.name")}{repository.name}
{t("repository.type")}{repository.type}
{t("repository.contact")} - -
{t("repository.description")}{repository.description}
{t("repository.creationDate")} - -
{t("repository.lastModified")} - -
- ); - } -} - -export default translate("repos")(RepositoryDetailTable); +//@flow +import React from "react"; +import type { Repository } from "@scm-manager/ui-types"; +import { MailLink, DateFromNow } from "@scm-manager/ui-components"; +import { translate } from "react-i18next"; + +type Props = { + repository: Repository, + // context props + t: string => string +}; + +class RepositoryDetailTable extends React.Component { + render() { + const { repository, t } = this.props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{t("repository.name")}{repository.name}
{t("repository.type")}{repository.type}
{t("repository.contact")} + +
{t("repository.description")}{repository.description}
{t("repository.creationDate")} + +
{t("repository.lastModified")} + +
+ ); + } +} + +export default translate("repos")(RepositoryDetailTable); diff --git a/scm-ui/src/repos/components/RepositoryDetails.js b/scm-ui/src/repos/components/RepositoryDetails.js index 99c88fec94..02d7f2f5ac 100644 --- a/scm-ui/src/repos/components/RepositoryDetails.js +++ b/scm-ui/src/repos/components/RepositoryDetails.js @@ -1,29 +1,30 @@ -//@flow -import React from "react"; -import type { Repository } from "@scm-manager/ui-types"; -import RepositoryDetailTable from "./RepositoryDetailTable"; -import { ExtensionPoint } from "@scm-manager/ui-extensions"; - -type Props = { - repository: Repository -}; - -class RepositoryDetails extends React.Component { - render() { - const { repository } = this.props; - return ( -
- -
- -
-
- ); - } -} - -export default RepositoryDetails; +//@flow +import React from "react"; +import type { Repository } from "@scm-manager/ui-types"; +import RepositoryDetailTable from "./RepositoryDetailTable"; +import { ExtensionPoint } from "@scm-manager/ui-extensions"; + +type Props = { + repository: Repository +}; + +class RepositoryDetails extends React.Component { + render() { + const { repository } = this.props; + return ( +
+ +
+
+ +
+
+ ); + } +} + +export default RepositoryDetails; diff --git a/scm-ui/src/repos/components/list/RepositoryEntry.js b/scm-ui/src/repos/components/list/RepositoryEntry.js index bc170144aa..b0b70fc861 100644 --- a/scm-ui/src/repos/components/list/RepositoryEntry.js +++ b/scm-ui/src/repos/components/list/RepositoryEntry.js @@ -9,15 +9,10 @@ import classNames from "classnames"; import RepositoryAvatar from "./RepositoryAvatar"; const styles = { - outer: { - position: "relative" - }, overlay: { position: "absolute", - left: 0, - top: 0, - bottom: 0, - right: 0 + height: "calc(120px - 1.5rem)", + width: "calc(50% - 3rem)" }, inner: { position: "relative", @@ -26,11 +21,16 @@ const styles = { }, innerLink: { pointerEvents: "all" + }, + centerImage: { + marginTop: "0.8em", + marginLeft: "1em !important" } }; type Props = { repository: Repository, + fullColumnWidth?: boolean, // context props classes: any }; @@ -44,7 +44,7 @@ class RepositoryEntry extends React.Component { if (repository._links["changesets"]) { return ( ); @@ -56,7 +56,7 @@ class RepositoryEntry extends React.Component { if (repository._links["sources"]) { return ( ); @@ -67,29 +67,40 @@ class RepositoryEntry extends React.Component { renderModifyLink = (repository: Repository, repositoryLink: string) => { if (repository._links["update"]) { return ( - + ); } return null; }; render() { - const { repository, classes } = this.props; + const { repository, classes, fullColumnWidth } = this.props; const repositoryLink = this.createLink(repository); + const halfColumn = fullColumnWidth ? "is-full" : "is-half"; return ( -
- +
+
-
+
-

+

{repository.name} -
- {repository.description}

+

{repository.description}

@@ -120,16 +123,22 @@ class Content extends React.Component { const fileSize = file.directory ? "" : ; if (!collapsed) { return ( -
- +
+
- + - + @@ -141,7 +150,7 @@ class Content extends React.Component { - +
{t("sources.content.path")}{file.path}{file.path}
{t("sources.content.branch")}{revision}{revision}
{t("sources.content.size")}
{t("sources.content.description")}{description}{description}
diff --git a/scm-ui/src/repos/sources/containers/Sources.js b/scm-ui/src/repos/sources/containers/Sources.js index 890ab595d0..810e2309ee 100644 --- a/scm-ui/src/repos/sources/containers/Sources.js +++ b/scm-ui/src/repos/sources/containers/Sources.js @@ -5,7 +5,8 @@ import { withRouter } from "react-router-dom"; import type { Branch, Repository } from "@scm-manager/ui-types"; import FileTree from "../components/FileTree"; import { ErrorNotification, Loading } from "@scm-manager/ui-components"; -import BranchSelector from "../../containers/BranchSelector"; +import BranchSelector from "../../../../../scm-ui-components/packages/ui-components/src/BranchSelector"; +import { translate } from "react-i18next"; import { fetchBranches, getBranches, @@ -32,7 +33,8 @@ type Props = { // Context props history: any, - match: any + match: any, + t: string => string }; class Sources extends React.Component { @@ -91,7 +93,7 @@ class Sources extends React.Component { if (currentFileIsDirectory) { return ( - <> +
{this.renderBranchSelector()} { path={path} baseUrl={baseUrl} /> - +
); } else { return ( @@ -109,13 +111,14 @@ class Sources extends React.Component { } renderBranchSelector = () => { - const { branches, revision } = this.props; + const { branches, revision, t } = this.props; if (branches) { return ( { this.branchSelected(b); }} @@ -160,6 +163,7 @@ const mapDispatchToProps = dispatch => { }; export default compose( + translate("repos"), withRouter, connect( mapStateToProps, diff --git a/scm-ui/src/repos/sources/modules/sources.js b/scm-ui/src/repos/sources/modules/sources.js index 5868c56df3..41ee7935df 100644 --- a/scm-ui/src/repos/sources/modules/sources.js +++ b/scm-ui/src/repos/sources/modules/sources.js @@ -25,8 +25,7 @@ export function fetchSources( dispatch(fetchSourcesSuccess(repository, revision, path, sources)); }) .catch(err => { - const error = new Error(`failed to fetch sources: ${err.message}`); - dispatch(fetchSourcesFailure(repository, revision, path, error)); + dispatch(fetchSourcesFailure(repository, revision, path, err)); }); }; } @@ -93,8 +92,8 @@ export default function reducer( ): any { if (action.itemId && action.type === FETCH_SOURCES_SUCCESS) { return { - [action.itemId]: action.payload, - ...state + ...state, + [action.itemId]: action.payload }; } return state; diff --git a/scm-ui/src/users/components/UserForm.js b/scm-ui/src/users/components/UserForm.js index bb9b0cbf41..2d3a519f15 100644 --- a/scm-ui/src/users/components/UserForm.js +++ b/scm-ui/src/users/components/UserForm.js @@ -105,41 +105,55 @@ class UserForm extends React.Component { } return (
- {nameField} - - - {passwordChangeField} - - - +
+
+ {nameField} + +
+
+ +
+
+
+
+ {passwordChangeField} + + +
+
+
+
+ +
+
); } diff --git a/scm-ui/src/users/components/table/Details.js b/scm-ui/src/users/components/table/Details.js index c967e4d0b4..1db5d2154c 100644 --- a/scm-ui/src/users/components/table/Details.js +++ b/scm-ui/src/users/components/table/Details.js @@ -1,66 +1,66 @@ -//@flow -import React from "react"; -import type { User } from "@scm-manager/ui-types"; -import { translate } from "react-i18next"; -import { Checkbox, MailLink, DateFromNow } from "@scm-manager/ui-components"; - -type Props = { - user: User, - t: string => string -}; - -class Details extends React.Component { - render() { - const { user, t } = this.props; - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{t("user.name")}{user.name}
{t("user.displayName")}{user.displayName}
{t("user.mail")} - -
{t("user.admin")} - -
{t("user.active")} - -
{t("user.type")}{user.type}
{t("user.creationDate")} - -
{t("user.lastModified")} - -
- ); - } -} - -export default translate("users")(Details); +//@flow +import React from "react"; +import type { User } from "@scm-manager/ui-types"; +import { translate } from "react-i18next"; +import { Checkbox, MailLink, DateFromNow } from "@scm-manager/ui-components"; + +type Props = { + user: User, + t: string => string +}; + +class Details extends React.Component { + render() { + const { user, t } = this.props; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{t("user.name")}{user.name}
{t("user.displayName")}{user.displayName}
{t("user.mail")} + +
{t("user.admin")} + +
{t("user.active")} + +
{t("user.type")}{user.type}
{t("user.creationDate")} + +
{t("user.lastModified")} + +
+ ); + } +} + +export default translate("users")(Details); diff --git a/scm-ui/src/users/components/table/UserRow.js b/scm-ui/src/users/components/table/UserRow.js index 6960009bea..c879d5e8f7 100644 --- a/scm-ui/src/users/components/table/UserRow.js +++ b/scm-ui/src/users/components/table/UserRow.js @@ -1,31 +1,31 @@ -// @flow -import React from "react"; -import { Link } from "react-router-dom"; -import type { User } from "@scm-manager/ui-types"; - -type Props = { - user: User -}; - -export default class UserRow extends React.Component { - renderLink(to: string, label: string) { - return {label}; - } - - render() { - const { user } = this.props; - const to = `/user/${user.name}`; - return ( - - {this.renderLink(to, user.name)} - {this.renderLink(to, user.displayName)} - - {user.mail} - - - - - - ); - } -} +// @flow +import React from "react"; +import { Link } from "react-router-dom"; +import type { User } from "@scm-manager/ui-types"; + +type Props = { + user: User +}; + +export default class UserRow extends React.Component { + renderLink(to: string, label: string) { + return {label}; + } + + render() { + const { user } = this.props; + const to = `/user/${user.name}`; + return ( + + {this.renderLink(to, user.name)} + {this.renderLink(to, user.displayName)} + + {user.mail} + + + + + + ); + } +} diff --git a/scm-ui/src/users/components/table/UserTable.js b/scm-ui/src/users/components/table/UserTable.js index 11d44da3ca..8febdb6011 100644 --- a/scm-ui/src/users/components/table/UserTable.js +++ b/scm-ui/src/users/components/table/UserTable.js @@ -1,35 +1,37 @@ -// @flow -import React from "react"; -import { translate } from "react-i18next"; -import UserRow from "./UserRow"; -import type { User } from "@scm-manager/ui-types"; - -type Props = { - t: string => string, - users: User[] -}; - -class UserTable extends React.Component { - render() { - const { users, t } = this.props; - return ( - - - - - - - - - - - {users.map((user, index) => { - return ; - })} - -
{t("user.name")}{t("user.displayName")}{t("user.mail")}{t("user.admin")}
- ); - } -} - -export default translate("users")(UserTable); +// @flow +import React from "react"; +import { translate } from "react-i18next"; +import UserRow from "./UserRow"; +import type { User } from "@scm-manager/ui-types"; + +type Props = { + t: string => string, + users: User[] +}; + +; + +class UserTable extends React.Component { + render() { + const { users, t } = this.props; + return ( + + + + + + + + + + + {users.map((user, index) => { + return ; + })} + +
{t("user.name")}{t("user.displayName")}{t("user.mail")}{t("user.admin")}
+ ); + } +} + +export default translate("users")(UserTable); \ No newline at end of file diff --git a/scm-ui/src/users/containers/Users.js b/scm-ui/src/users/containers/Users.js index 48c20c88ec..cbb33dc68b 100644 --- a/scm-ui/src/users/containers/Users.js +++ b/scm-ui/src/users/containers/Users.js @@ -1,143 +1,143 @@ -// @flow -import React from "react"; -import type { History } from "history"; -import { connect } from "react-redux"; -import { translate } from "react-i18next"; - -import { - fetchUsersByPage, - fetchUsersByLink, - getUsersFromState, - selectListAsCollection, - isPermittedToCreateUsers, - isFetchUsersPending, - getFetchUsersFailure -} from "../modules/users"; - -import { Page, Paginator } from "@scm-manager/ui-components"; -import { UserTable } from "./../components/table"; -import type { User, PagedCollection } from "@scm-manager/ui-types"; -import CreateUserButton from "../components/buttons/CreateUserButton"; -import { getUsersLink } from "../../modules/indexResource"; - -type Props = { - users: User[], - loading: boolean, - error: Error, - canAddUsers: boolean, - list: PagedCollection, - page: number, - usersLink: string, - - // context objects - t: string => string, - history: History, - - // dispatch functions - fetchUsersByPage: (link: string, page: number) => void, - fetchUsersByLink: (link: string) => void -}; - -class Users extends React.Component { - componentDidMount() { - this.props.fetchUsersByPage(this.props.usersLink, this.props.page); - } - - onPageChange = (link: string) => { - this.props.fetchUsersByLink(link); - }; - - /** - * reflect page transitions in the uri - */ - componentDidUpdate() { - const { page, list } = this.props; - if (list && (list.page || list.page === 0)) { - // backend starts paging by 0 - const statePage: number = list.page + 1; - if (page !== statePage) { - this.props.history.push(`/users/${statePage}`); - } - } - } - - render() { - const { users, loading, error, t } = this.props; - return ( - - - {this.renderPaginator()} - {this.renderCreateButton()} - - ); - } - - renderPaginator() { - const { list } = this.props; - if (list) { - return ; - } - return null; - } - - renderCreateButton() { - if (this.props.canAddUsers) { - return ; - } else { - return; - } - } -} - -const getPageFromProps = props => { - let page = props.match.params.page; - if (page) { - page = parseInt(page, 10); - } else { - page = 1; - } - return page; -}; - -const mapStateToProps = (state, ownProps) => { - const users = getUsersFromState(state); - const loading = isFetchUsersPending(state); - const error = getFetchUsersFailure(state); - - const usersLink = getUsersLink(state); - - const page = getPageFromProps(ownProps); - const canAddUsers = isPermittedToCreateUsers(state); - const list = selectListAsCollection(state); - - return { - users, - loading, - error, - canAddUsers, - list, - page, - usersLink - }; -}; - -const mapDispatchToProps = dispatch => { - return { - fetchUsersByPage: (link: string, page: number) => { - dispatch(fetchUsersByPage(link, page)); - }, - fetchUsersByLink: (link: string) => { - dispatch(fetchUsersByLink(link)); - } - }; -}; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(translate("users")(Users)); +// @flow +import React from "react"; +import type { History } from "history"; +import { connect } from "react-redux"; +import { translate } from "react-i18next"; + +import { + fetchUsersByPage, + fetchUsersByLink, + getUsersFromState, + selectListAsCollection, + isPermittedToCreateUsers, + isFetchUsersPending, + getFetchUsersFailure +} from "../modules/users"; + +import { Page, Paginator } from "@scm-manager/ui-components"; +import { UserTable } from "./../components/table"; +import type { User, PagedCollection } from "@scm-manager/ui-types"; +import CreateUserButton from "../components/buttons/CreateUserButton"; +import { getUsersLink } from "../../modules/indexResource"; + +type Props = { + users: User[], + loading: boolean, + error: Error, + canAddUsers: boolean, + list: PagedCollection, + page: number, + usersLink: string, + + // context objects + t: string => string, + history: History, + + // dispatch functions + fetchUsersByPage: (link: string, page: number) => void, + fetchUsersByLink: (link: string) => void +}; + +class Users extends React.Component { + componentDidMount() { + this.props.fetchUsersByPage(this.props.usersLink, this.props.page); + } + + onPageChange = (link: string) => { + this.props.fetchUsersByLink(link); + }; + + /** + * reflect page transitions in the uri + */ + componentDidUpdate() { + const { page, list } = this.props; + if (list && (list.page || list.page === 0)) { + // backend starts paging by 0 + const statePage: number = list.page + 1; + if (page !== statePage) { + this.props.history.push(`/users/${statePage}`); + } + } + } + + render() { + const { users, loading, error, t } = this.props; + return ( + + + {this.renderPaginator()} + {this.renderCreateButton()} + + ); + } + + renderPaginator() { + const { list } = this.props; + if (list) { + return ; + } + return null; + } + + renderCreateButton() { + if (this.props.canAddUsers) { + return ; + } else { + return; + } + } +} + +const getPageFromProps = props => { + let page = props.match.params.page; + if (page) { + page = parseInt(page, 10); + } else { + page = 1; + } + return page; +}; + +const mapStateToProps = (state, ownProps) => { + const users = getUsersFromState(state); + const loading = isFetchUsersPending(state); + const error = getFetchUsersFailure(state); + + const usersLink = getUsersLink(state); + + const page = getPageFromProps(ownProps); + const canAddUsers = isPermittedToCreateUsers(state); + const list = selectListAsCollection(state); + + return { + users, + loading, + error, + canAddUsers, + list, + page, + usersLink + }; +}; + +const mapDispatchToProps = dispatch => { + return { + fetchUsersByPage: (link: string, page: number) => { + dispatch(fetchUsersByPage(link, page)); + }, + fetchUsersByLink: (link: string) => { + dispatch(fetchUsersByLink(link)); + } + }; +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(translate("users")(Users)); diff --git a/scm-ui/src/users/modules/users.js b/scm-ui/src/users/modules/users.js index fe751d13d4..ab330d9ffd 100644 --- a/scm-ui/src/users/modules/users.js +++ b/scm-ui/src/users/modules/users.js @@ -35,8 +35,6 @@ export const DELETE_USER_FAILURE = `${DELETE_USER}_${types.FAILURE_SUFFIX}`; const CONTENT_TYPE_USER = "application/vnd.scmm-user+json;v=2"; -// TODO i18n for error messages - // fetch users export function fetchUsers(link: string) { @@ -57,9 +55,8 @@ export function fetchUsersByLink(link: string) { .then(data => { dispatch(fetchUsersSuccess(data)); }) - .catch(cause => { - const error = new Error(`could not fetch users: ${cause.message}`); - dispatch(fetchUsersFailure(link, error)); + .catch(err => { + dispatch(fetchUsersFailure(link, err)); }); }; } @@ -108,9 +105,8 @@ function fetchUser(link: string, name: string) { .then(data => { dispatch(fetchUserSuccess(data)); }) - .catch(cause => { - const error = new Error(`could not fetch user: ${cause.message}`); - dispatch(fetchUserFailure(name, error)); + .catch(err => { + dispatch(fetchUserFailure(name, err)); }); }; } @@ -155,13 +151,7 @@ export function createUser(link: string, user: User, callback?: () => void) { callback(); } }) - .catch(err => - dispatch( - createUserFailure( - new Error(`failed to add user ${user.name}: ${err.message}`) - ) - ) - ); + .catch(err => dispatch(createUserFailure(err))); }; } @@ -260,11 +250,8 @@ export function deleteUser(user: User, callback?: () => void) { callback(); } }) - .catch(cause => { - const error = new Error( - `could not delete user ${user.name}: ${cause.message}` - ); - dispatch(deleteUserFailure(user, error)); + .catch(err => { + dispatch(deleteUserFailure(user, err)); }); }; } diff --git a/scm-ui/styles/scm.css b/scm-ui/styles/scm.css index 8de75b3a6c..9027cb9f87 100644 --- a/scm-ui/styles/scm.css +++ b/scm-ui/styles/scm.css @@ -1,10223 +1,54 @@ -.is-ellipsis-overflow { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; } - -.has-rounded-border { - border-radius: 0.25rem; } - -.is-full-width { - width: 100%; } - -.fitParent { - margin: 0 !important; - padding: 0 0 0 3.8em !important; } - -.main { - min-height: calc(100vh - 260px); } - -.footer { - height: 50px; } - -/*! bulma.io v0.7.1 | MIT License | github.com/jgthms/bulma */ -@keyframes spinAround { - from { - transform: rotate(0deg); } - to { - transform: rotate(359deg); } } - -.delete, .modal-close, .is-unselectable, .button, .file, .breadcrumb, .pagination-previous, -.pagination-next, -.pagination-link, -.pagination-ellipsis, .tabs { - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; } - -.select:not(.is-multiple):not(.is-loading)::after, .navbar-link::after { - border: 3px solid transparent; - border-radius: 2px; - border-right: 0; - border-top: 0; - content: " "; - display: block; - height: 0.625em; - margin-top: -0.4375em; - pointer-events: none; - position: absolute; - top: 50%; - transform: rotate(-45deg); - transform-origin: center; - width: 0.625em; } - -.box:not(:last-child), .content:not(:last-child), .notification:not(:last-child), .progress:not(:last-child), .table:not(:last-child), .table-container:not(:last-child), .title:not(:last-child), -.subtitle:not(:last-child), .block:not(:last-child), .highlight:not(:last-child), .breadcrumb:not(:last-child), .level:not(:last-child), .message:not(:last-child), .tabs:not(:last-child) { - margin-bottom: 1.5rem; } - -.delete, .modal-close { - -moz-appearance: none; - -webkit-appearance: none; - background-color: rgba(10, 10, 10, 0.2); - border: none; - border-radius: 290486px; - cursor: pointer; - display: inline-block; - flex-grow: 0; - flex-shrink: 0; - font-size: 0; - height: 20px; - max-height: 20px; - max-width: 20px; - min-height: 20px; - min-width: 20px; - outline: none; - position: relative; - vertical-align: top; - width: 20px; } - .delete::before, .modal-close::before, .delete::after, .modal-close::after { - background-color: white; - content: ""; - display: block; - left: 50%; - position: absolute; - top: 50%; - transform: translateX(-50%) translateY(-50%) rotate(45deg); - transform-origin: center center; } - .delete::before, .modal-close::before { - height: 2px; - width: 50%; } - .delete::after, .modal-close::after { - height: 50%; - width: 2px; } - .delete:hover, .modal-close:hover, .delete:focus, .modal-close:focus { - background-color: rgba(10, 10, 10, 0.3); } - .delete:active, .modal-close:active { - background-color: rgba(10, 10, 10, 0.4); } - .is-small.delete, .is-small.modal-close { - height: 16px; - max-height: 16px; - max-width: 16px; - min-height: 16px; - min-width: 16px; - width: 16px; } - .is-medium.delete, .is-medium.modal-close { - height: 24px; - max-height: 24px; - max-width: 24px; - min-height: 24px; - min-width: 24px; - width: 24px; } - .is-large.delete, .is-large.modal-close { - height: 32px; - max-height: 32px; - max-width: 32px; - min-height: 32px; - min-width: 32px; - width: 32px; } - -.button.is-loading::after, .select.is-loading::after, .control.is-loading::after, .loader { - animation: spinAround 500ms infinite linear; - border: 2px solid #dbdbdb; - border-radius: 290486px; - border-right-color: transparent; - border-top-color: transparent; - content: ""; - display: block; - height: 1em; - position: relative; - width: 1em; } - -.is-overlay, .image.is-square img, .image.is-1by1 img, .image.is-5by4 img, .image.is-4by3 img, .image.is-3by2 img, .image.is-5by3 img, .image.is-16by9 img, .image.is-2by1 img, .image.is-3by1 img, .image.is-4by5 img, .image.is-3by4 img, .image.is-2by3 img, .image.is-3by5 img, .image.is-9by16 img, .image.is-1by2 img, .image.is-1by3 img, .modal, .modal-background, .hero-video { - bottom: 0; - left: 0; - position: absolute; - right: 0; - top: 0; } - -.button, .input, -.textarea, .select select, .file-cta, -.file-name, .pagination-previous, -.pagination-next, -.pagination-link, -.pagination-ellipsis { - -moz-appearance: none; - -webkit-appearance: none; - align-items: center; - border: 1px solid transparent; - border-radius: 4px; - box-shadow: none; - display: inline-flex; - font-size: 1rem; - height: 2.25em; - justify-content: flex-start; - line-height: 1.5; - padding-bottom: calc(0.375em - 1px); - padding-left: calc(0.625em - 1px); - padding-right: calc(0.625em - 1px); - padding-top: calc(0.375em - 1px); - position: relative; - vertical-align: top; } - .button:focus, .input:focus, - .textarea:focus, .select select:focus, .file-cta:focus, - .file-name:focus, .pagination-previous:focus, - .pagination-next:focus, - .pagination-link:focus, - .pagination-ellipsis:focus, .is-focused.button, .is-focused.input, - .is-focused.textarea, .select select.is-focused, .is-focused.file-cta, - .is-focused.file-name, .is-focused.pagination-previous, - .is-focused.pagination-next, - .is-focused.pagination-link, - .is-focused.pagination-ellipsis, .button:active, .input:active, - .textarea:active, .select select:active, .file-cta:active, - .file-name:active, .pagination-previous:active, - .pagination-next:active, - .pagination-link:active, - .pagination-ellipsis:active, .is-active.button, .is-active.input, - .is-active.textarea, .select select.is-active, .is-active.file-cta, - .is-active.file-name, .is-active.pagination-previous, - .is-active.pagination-next, - .is-active.pagination-link, - .is-active.pagination-ellipsis { - outline: none; } - .button[disabled], .input[disabled], - .textarea[disabled], .select select[disabled], .file-cta[disabled], - .file-name[disabled], .pagination-previous[disabled], - .pagination-next[disabled], - .pagination-link[disabled], - .pagination-ellipsis[disabled] { - cursor: not-allowed; } - -/*! minireset.css v0.0.3 | MIT License | github.com/jgthms/minireset.css */ -html, -body, -p, -ol, -ul, -li, -dl, -dt, -dd, -blockquote, -figure, -fieldset, -legend, -textarea, -pre, -iframe, -hr, -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0; - padding: 0; } - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: 100%; - font-weight: normal; } - -ul { - list-style: none; } - -button, -input, -select, -textarea { - margin: 0; } - -html { - box-sizing: border-box; } - -*, *::before, *::after { - box-sizing: inherit; } - -img, -audio, -video { - height: auto; - max-width: 100%; } - -iframe { - border: 0; } - -table { - border-collapse: collapse; - border-spacing: 0; } - -td, -th { - padding: 0; - text-align: left; } - -html { - background-color: white; - font-size: 16px; - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - min-width: 300px; - overflow-x: hidden; - overflow-y: scroll; - text-rendering: optimizeLegibility; - text-size-adjust: 100%; } - -article, -aside, -figure, -footer, -header, -hgroup, -section { - display: block; } - -body, -button, -input, -select, -textarea { - font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif; } - -code, -pre { - -moz-osx-font-smoothing: auto; - -webkit-font-smoothing: auto; - font-family: monospace; } - -body { - color: #4a4a4a; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; } - -a { - color: #33B2E8; - cursor: pointer; - text-decoration: none; } - a strong { - color: currentColor; } - a:hover { - color: #363636; } - -code { - background-color: whitesmoke; - color: #ff3860; - font-size: 0.875em; - font-weight: normal; - padding: 0.25em 0.5em 0.25em; } - -hr { - background-color: whitesmoke; - border: none; - display: block; - height: 2px; - margin: 1.5rem 0; } - -img { - height: auto; - max-width: 100%; } - -input[type="checkbox"], -input[type="radio"] { - vertical-align: baseline; } - -small { - font-size: 0.875em; } - -span { - font-style: inherit; - font-weight: inherit; } - -strong { - color: #363636; - font-weight: 700; } - -pre { - -webkit-overflow-scrolling: touch; - background-color: whitesmoke; - color: #4a4a4a; - font-size: 0.875em; - overflow-x: auto; - padding: 1.25rem 1.5rem; - white-space: pre; - word-wrap: normal; } - pre code { - background-color: transparent; - color: currentColor; - font-size: 1em; - padding: 0; } - -table td, -table th { - text-align: left; - vertical-align: top; } - -table th { - color: #363636; } - -.is-clearfix::after { - clear: both; - content: " "; - display: table; } - -.is-pulled-left { - float: left !important; } - -.is-pulled-right { - float: right !important; } - -.is-clipped { - overflow: hidden !important; } - -.is-size-1 { - font-size: 3rem !important; } - -.is-size-2 { - font-size: 2.5rem !important; } - -.is-size-3 { - font-size: 2rem !important; } - -.is-size-4 { - font-size: 1.5rem !important; } - -.is-size-5 { - font-size: 1.25rem !important; } - -.is-size-6 { - font-size: 1rem !important; } - -.is-size-7 { - font-size: 0.75rem !important; } - -@media screen and (max-width: 768px) { - .is-size-1-mobile { - font-size: 3rem !important; } - .is-size-2-mobile { - font-size: 2.5rem !important; } - .is-size-3-mobile { - font-size: 2rem !important; } - .is-size-4-mobile { - font-size: 1.5rem !important; } - .is-size-5-mobile { - font-size: 1.25rem !important; } - .is-size-6-mobile { - font-size: 1rem !important; } - .is-size-7-mobile { - font-size: 0.75rem !important; } } - -@media screen and (min-width: 769px), print { - .is-size-1-tablet { - font-size: 3rem !important; } - .is-size-2-tablet { - font-size: 2.5rem !important; } - .is-size-3-tablet { - font-size: 2rem !important; } - .is-size-4-tablet { - font-size: 1.5rem !important; } - .is-size-5-tablet { - font-size: 1.25rem !important; } - .is-size-6-tablet { - font-size: 1rem !important; } - .is-size-7-tablet { - font-size: 0.75rem !important; } } - -@media screen and (max-width: 1087px) { - .is-size-1-touch { - font-size: 3rem !important; } - .is-size-2-touch { - font-size: 2.5rem !important; } - .is-size-3-touch { - font-size: 2rem !important; } - .is-size-4-touch { - font-size: 1.5rem !important; } - .is-size-5-touch { - font-size: 1.25rem !important; } - .is-size-6-touch { - font-size: 1rem !important; } - .is-size-7-touch { - font-size: 0.75rem !important; } } - -@media screen and (min-width: 1088px) { - .is-size-1-desktop { - font-size: 3rem !important; } - .is-size-2-desktop { - font-size: 2.5rem !important; } - .is-size-3-desktop { - font-size: 2rem !important; } - .is-size-4-desktop { - font-size: 1.5rem !important; } - .is-size-5-desktop { - font-size: 1.25rem !important; } - .is-size-6-desktop { - font-size: 1rem !important; } - .is-size-7-desktop { - font-size: 0.75rem !important; } } - -@media screen and (min-width: 1280px) { - .is-size-1-widescreen { - font-size: 3rem !important; } - .is-size-2-widescreen { - font-size: 2.5rem !important; } - .is-size-3-widescreen { - font-size: 2rem !important; } - .is-size-4-widescreen { - font-size: 1.5rem !important; } - .is-size-5-widescreen { - font-size: 1.25rem !important; } - .is-size-6-widescreen { - font-size: 1rem !important; } - .is-size-7-widescreen { - font-size: 0.75rem !important; } } - -@media screen and (min-width: 1472px) { - .is-size-1-fullhd { - font-size: 3rem !important; } - .is-size-2-fullhd { - font-size: 2.5rem !important; } - .is-size-3-fullhd { - font-size: 2rem !important; } - .is-size-4-fullhd { - font-size: 1.5rem !important; } - .is-size-5-fullhd { - font-size: 1.25rem !important; } - .is-size-6-fullhd { - font-size: 1rem !important; } - .is-size-7-fullhd { - font-size: 0.75rem !important; } } - -.has-text-centered { - text-align: center !important; } - -.has-text-justified { - text-align: justify !important; } - -.has-text-left { - text-align: left !important; } - -.has-text-right { - text-align: right !important; } - -@media screen and (max-width: 768px) { - .has-text-centered-mobile { - text-align: center !important; } } - -@media screen and (min-width: 769px), print { - .has-text-centered-tablet { - text-align: center !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .has-text-centered-tablet-only { - text-align: center !important; } } - -@media screen and (max-width: 1087px) { - .has-text-centered-touch { - text-align: center !important; } } - -@media screen and (min-width: 1088px) { - .has-text-centered-desktop { - text-align: center !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .has-text-centered-desktop-only { - text-align: center !important; } } - -@media screen and (min-width: 1280px) { - .has-text-centered-widescreen { - text-align: center !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .has-text-centered-widescreen-only { - text-align: center !important; } } - -@media screen and (min-width: 1472px) { - .has-text-centered-fullhd { - text-align: center !important; } } - -@media screen and (max-width: 768px) { - .has-text-justified-mobile { - text-align: justify !important; } } - -@media screen and (min-width: 769px), print { - .has-text-justified-tablet { - text-align: justify !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .has-text-justified-tablet-only { - text-align: justify !important; } } - -@media screen and (max-width: 1087px) { - .has-text-justified-touch { - text-align: justify !important; } } - -@media screen and (min-width: 1088px) { - .has-text-justified-desktop { - text-align: justify !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .has-text-justified-desktop-only { - text-align: justify !important; } } - -@media screen and (min-width: 1280px) { - .has-text-justified-widescreen { - text-align: justify !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .has-text-justified-widescreen-only { - text-align: justify !important; } } - -@media screen and (min-width: 1472px) { - .has-text-justified-fullhd { - text-align: justify !important; } } - -@media screen and (max-width: 768px) { - .has-text-left-mobile { - text-align: left !important; } } - -@media screen and (min-width: 769px), print { - .has-text-left-tablet { - text-align: left !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .has-text-left-tablet-only { - text-align: left !important; } } - -@media screen and (max-width: 1087px) { - .has-text-left-touch { - text-align: left !important; } } - -@media screen and (min-width: 1088px) { - .has-text-left-desktop { - text-align: left !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .has-text-left-desktop-only { - text-align: left !important; } } - -@media screen and (min-width: 1280px) { - .has-text-left-widescreen { - text-align: left !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .has-text-left-widescreen-only { - text-align: left !important; } } - -@media screen and (min-width: 1472px) { - .has-text-left-fullhd { - text-align: left !important; } } - -@media screen and (max-width: 768px) { - .has-text-right-mobile { - text-align: right !important; } } - -@media screen and (min-width: 769px), print { - .has-text-right-tablet { - text-align: right !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .has-text-right-tablet-only { - text-align: right !important; } } - -@media screen and (max-width: 1087px) { - .has-text-right-touch { - text-align: right !important; } } - -@media screen and (min-width: 1088px) { - .has-text-right-desktop { - text-align: right !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .has-text-right-desktop-only { - text-align: right !important; } } - -@media screen and (min-width: 1280px) { - .has-text-right-widescreen { - text-align: right !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .has-text-right-widescreen-only { - text-align: right !important; } } - -@media screen and (min-width: 1472px) { - .has-text-right-fullhd { - text-align: right !important; } } - -.is-capitalized { - text-transform: capitalize !important; } - -.is-lowercase { - text-transform: lowercase !important; } - -.is-uppercase { - text-transform: uppercase !important; } - -.is-italic { - font-style: italic !important; } - -.has-text-white { - color: white !important; } - -a.has-text-white:hover, a.has-text-white:focus { - color: #e6e6e6 !important; } - -.has-background-white { - background-color: white !important; } - -.has-text-black { - color: #0a0a0a !important; } - -a.has-text-black:hover, a.has-text-black:focus { - color: black !important; } - -.has-background-black { - background-color: #0a0a0a !important; } - -.has-text-light { - color: whitesmoke !important; } - -a.has-text-light:hover, a.has-text-light:focus { - color: #dbdbdb !important; } - -.has-background-light { - background-color: whitesmoke !important; } - -.has-text-dark { - color: #363636 !important; } - -a.has-text-dark:hover, a.has-text-dark:focus { - color: #1c1c1c !important; } - -.has-background-dark { - background-color: #363636 !important; } - -.has-text-primary { - color: #00d1b2 !important; } - -a.has-text-primary:hover, a.has-text-primary:focus { - color: #009e86 !important; } - -.has-background-primary { - background-color: #00d1b2 !important; } - -.has-text-link { - color: #33B2E8 !important; } - -a.has-text-link:hover, a.has-text-link:focus { - color: #1899d0 !important; } - -.has-background-link { - background-color: #33B2E8 !important; } - -.has-text-info { - color: #209cee !important; } - -a.has-text-info:hover, a.has-text-info:focus { - color: #0f81cc !important; } - -.has-background-info { - background-color: #209cee !important; } - -.has-text-success { - color: #23d160 !important; } - -a.has-text-success:hover, a.has-text-success:focus { - color: #1ca64c !important; } - -.has-background-success { - background-color: #23d160 !important; } - -.has-text-warning { - color: #ffdd57 !important; } - -a.has-text-warning:hover, a.has-text-warning:focus { - color: #ffd324 !important; } - -.has-background-warning { - background-color: #ffdd57 !important; } - -.has-text-danger { - color: #ff3860 !important; } - -a.has-text-danger:hover, a.has-text-danger:focus { - color: #ff0537 !important; } - -.has-background-danger { - background-color: #ff3860 !important; } - -.has-text-black-bis { - color: #121212 !important; } - -.has-background-black-bis { - background-color: #121212 !important; } - -.has-text-black-ter { - color: #242424 !important; } - -.has-background-black-ter { - background-color: #242424 !important; } - -.has-text-grey-darker { - color: #363636 !important; } - -.has-background-grey-darker { - background-color: #363636 !important; } - -.has-text-grey-dark { - color: #4a4a4a !important; } - -.has-background-grey-dark { - background-color: #4a4a4a !important; } - -.has-text-grey { - color: #7a7a7a !important; } - -.has-background-grey { - background-color: #7a7a7a !important; } - -.has-text-grey-light { - color: #b5b5b5 !important; } - -.has-background-grey-light { - background-color: #b5b5b5 !important; } - -.has-text-grey-lighter { - color: #dbdbdb !important; } - -.has-background-grey-lighter { - background-color: #dbdbdb !important; } - -.has-text-white-ter { - color: whitesmoke !important; } - -.has-background-white-ter { - background-color: whitesmoke !important; } - -.has-text-white-bis { - color: #fafafa !important; } - -.has-background-white-bis { - background-color: #fafafa !important; } - -.has-text-weight-light { - font-weight: 300 !important; } - -.has-text-weight-normal { - font-weight: 400 !important; } - -.has-text-weight-semibold { - font-weight: 600 !important; } - -.has-text-weight-bold { - font-weight: 700 !important; } - -.is-block { - display: block !important; } - -@media screen and (max-width: 768px) { - .is-block-mobile { - display: block !important; } } - -@media screen and (min-width: 769px), print { - .is-block-tablet { - display: block !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .is-block-tablet-only { - display: block !important; } } - -@media screen and (max-width: 1087px) { - .is-block-touch { - display: block !important; } } - -@media screen and (min-width: 1088px) { - .is-block-desktop { - display: block !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .is-block-desktop-only { - display: block !important; } } - -@media screen and (min-width: 1280px) { - .is-block-widescreen { - display: block !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .is-block-widescreen-only { - display: block !important; } } - -@media screen and (min-width: 1472px) { - .is-block-fullhd { - display: block !important; } } - -.is-flex { - display: flex !important; } - -@media screen and (max-width: 768px) { - .is-flex-mobile { - display: flex !important; } } - -@media screen and (min-width: 769px), print { - .is-flex-tablet { - display: flex !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .is-flex-tablet-only { - display: flex !important; } } - -@media screen and (max-width: 1087px) { - .is-flex-touch { - display: flex !important; } } - -@media screen and (min-width: 1088px) { - .is-flex-desktop { - display: flex !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .is-flex-desktop-only { - display: flex !important; } } - -@media screen and (min-width: 1280px) { - .is-flex-widescreen { - display: flex !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .is-flex-widescreen-only { - display: flex !important; } } - -@media screen and (min-width: 1472px) { - .is-flex-fullhd { - display: flex !important; } } - -.is-inline { - display: inline !important; } - -@media screen and (max-width: 768px) { - .is-inline-mobile { - display: inline !important; } } - -@media screen and (min-width: 769px), print { - .is-inline-tablet { - display: inline !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .is-inline-tablet-only { - display: inline !important; } } - -@media screen and (max-width: 1087px) { - .is-inline-touch { - display: inline !important; } } - -@media screen and (min-width: 1088px) { - .is-inline-desktop { - display: inline !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .is-inline-desktop-only { - display: inline !important; } } - -@media screen and (min-width: 1280px) { - .is-inline-widescreen { - display: inline !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .is-inline-widescreen-only { - display: inline !important; } } - -@media screen and (min-width: 1472px) { - .is-inline-fullhd { - display: inline !important; } } - -.is-inline-block { - display: inline-block !important; } - -@media screen and (max-width: 768px) { - .is-inline-block-mobile { - display: inline-block !important; } } - -@media screen and (min-width: 769px), print { - .is-inline-block-tablet { - display: inline-block !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .is-inline-block-tablet-only { - display: inline-block !important; } } - -@media screen and (max-width: 1087px) { - .is-inline-block-touch { - display: inline-block !important; } } - -@media screen and (min-width: 1088px) { - .is-inline-block-desktop { - display: inline-block !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .is-inline-block-desktop-only { - display: inline-block !important; } } - -@media screen and (min-width: 1280px) { - .is-inline-block-widescreen { - display: inline-block !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .is-inline-block-widescreen-only { - display: inline-block !important; } } - -@media screen and (min-width: 1472px) { - .is-inline-block-fullhd { - display: inline-block !important; } } - -.is-inline-flex { - display: inline-flex !important; } - -@media screen and (max-width: 768px) { - .is-inline-flex-mobile { - display: inline-flex !important; } } - -@media screen and (min-width: 769px), print { - .is-inline-flex-tablet { - display: inline-flex !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .is-inline-flex-tablet-only { - display: inline-flex !important; } } - -@media screen and (max-width: 1087px) { - .is-inline-flex-touch { - display: inline-flex !important; } } - -@media screen and (min-width: 1088px) { - .is-inline-flex-desktop { - display: inline-flex !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .is-inline-flex-desktop-only { - display: inline-flex !important; } } - -@media screen and (min-width: 1280px) { - .is-inline-flex-widescreen { - display: inline-flex !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .is-inline-flex-widescreen-only { - display: inline-flex !important; } } - -@media screen and (min-width: 1472px) { - .is-inline-flex-fullhd { - display: inline-flex !important; } } - -.is-hidden { - display: none !important; } - -@media screen and (max-width: 768px) { - .is-hidden-mobile { - display: none !important; } } - -@media screen and (min-width: 769px), print { - .is-hidden-tablet { - display: none !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .is-hidden-tablet-only { - display: none !important; } } - -@media screen and (max-width: 1087px) { - .is-hidden-touch { - display: none !important; } } - -@media screen and (min-width: 1088px) { - .is-hidden-desktop { - display: none !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .is-hidden-desktop-only { - display: none !important; } } - -@media screen and (min-width: 1280px) { - .is-hidden-widescreen { - display: none !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .is-hidden-widescreen-only { - display: none !important; } } - -@media screen and (min-width: 1472px) { - .is-hidden-fullhd { - display: none !important; } } - -.is-invisible { - visibility: hidden !important; } - -@media screen and (max-width: 768px) { - .is-invisible-mobile { - visibility: hidden !important; } } - -@media screen and (min-width: 769px), print { - .is-invisible-tablet { - visibility: hidden !important; } } - -@media screen and (min-width: 769px) and (max-width: 1087px) { - .is-invisible-tablet-only { - visibility: hidden !important; } } - -@media screen and (max-width: 1087px) { - .is-invisible-touch { - visibility: hidden !important; } } - -@media screen and (min-width: 1088px) { - .is-invisible-desktop { - visibility: hidden !important; } } - -@media screen and (min-width: 1088px) and (max-width: 1279px) { - .is-invisible-desktop-only { - visibility: hidden !important; } } - -@media screen and (min-width: 1280px) { - .is-invisible-widescreen { - visibility: hidden !important; } } - -@media screen and (min-width: 1280px) and (max-width: 1471px) { - .is-invisible-widescreen-only { - visibility: hidden !important; } } - -@media screen and (min-width: 1472px) { - .is-invisible-fullhd { - visibility: hidden !important; } } - -.is-marginless { - margin: 0 !important; } - -.is-paddingless { - padding: 0 !important; } - -.is-radiusless { - border-radius: 0 !important; } - -.is-shadowless { - box-shadow: none !important; } - -.box { - background-color: white; - border-radius: 6px; - box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); - color: #4a4a4a; - display: block; - padding: 1.25rem; } - -a.box:hover, a.box:focus { - box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px #33B2E8; } - -a.box:active { - box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2), 0 0 0 1px #33B2E8; } - -.button { - background-color: white; - border-color: #dbdbdb; - border-width: 1px; - color: #363636; - cursor: pointer; - justify-content: center; - padding-bottom: calc(0.375em - 1px); - padding-left: 0.75em; - padding-right: 0.75em; - padding-top: calc(0.375em - 1px); - text-align: center; - white-space: nowrap; } - .button strong { - color: inherit; } - .button .icon, .button .icon.is-small, .button .icon.is-medium, .button .icon.is-large { - height: 1.5em; - width: 1.5em; } - .button .icon:first-child:not(:last-child) { - margin-left: calc(-0.375em - 1px); - margin-right: 0.1875em; } - .button .icon:last-child:not(:first-child) { - margin-left: 0.1875em; - margin-right: calc(-0.375em - 1px); } - .button .icon:first-child:last-child { - margin-left: calc(-0.375em - 1px); - margin-right: calc(-0.375em - 1px); } - .button:hover, .button.is-hovered { - border-color: #b5b5b5; - color: #363636; } - .button:focus, .button.is-focused { - border-color: #33B2E8; - color: #363636; } - .button:focus:not(:active), .button.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(51, 178, 232, 0.25); } - .button:active, .button.is-active { - border-color: #4a4a4a; - color: #363636; } - .button.is-text { - background-color: transparent; - border-color: transparent; - color: #4a4a4a; - text-decoration: underline; } - .button.is-text:hover, .button.is-text.is-hovered, .button.is-text:focus, .button.is-text.is-focused { - background-color: whitesmoke; - color: #363636; } - .button.is-text:active, .button.is-text.is-active { - background-color: #e8e8e8; - color: #363636; } - .button.is-text[disabled] { - background-color: transparent; - border-color: transparent; - box-shadow: none; } - .button.is-white { - background-color: white; - border-color: transparent; - color: #0a0a0a; } - .button.is-white:hover, .button.is-white.is-hovered { - background-color: #f9f9f9; - border-color: transparent; - color: #0a0a0a; } - .button.is-white:focus, .button.is-white.is-focused { - border-color: transparent; - color: #0a0a0a; } - .button.is-white:focus:not(:active), .button.is-white.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } - .button.is-white:active, .button.is-white.is-active { - background-color: #f2f2f2; - border-color: transparent; - color: #0a0a0a; } - .button.is-white[disabled] { - background-color: white; - border-color: transparent; - box-shadow: none; } - .button.is-white.is-inverted { - background-color: #0a0a0a; - color: white; } - .button.is-white.is-inverted:hover { - background-color: black; } - .button.is-white.is-inverted[disabled] { - background-color: #0a0a0a; - border-color: transparent; - box-shadow: none; - color: white; } - .button.is-white.is-loading::after { - border-color: transparent transparent #0a0a0a #0a0a0a !important; } - .button.is-white.is-outlined { - background-color: transparent; - border-color: white; - color: white; } - .button.is-white.is-outlined:hover, .button.is-white.is-outlined:focus { - background-color: white; - border-color: white; - color: #0a0a0a; } - .button.is-white.is-outlined.is-loading::after { - border-color: transparent transparent white white !important; } - .button.is-white.is-outlined[disabled] { - background-color: transparent; - border-color: white; - box-shadow: none; - color: white; } - .button.is-white.is-inverted.is-outlined { - background-color: transparent; - border-color: #0a0a0a; - color: #0a0a0a; } - .button.is-white.is-inverted.is-outlined:hover, .button.is-white.is-inverted.is-outlined:focus { - background-color: #0a0a0a; - color: white; } - .button.is-white.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: #0a0a0a; - box-shadow: none; - color: #0a0a0a; } - .button.is-black { - background-color: #0a0a0a; - border-color: transparent; - color: white; } - .button.is-black:hover, .button.is-black.is-hovered { - background-color: #040404; - border-color: transparent; - color: white; } - .button.is-black:focus, .button.is-black.is-focused { - border-color: transparent; - color: white; } - .button.is-black:focus:not(:active), .button.is-black.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } - .button.is-black:active, .button.is-black.is-active { - background-color: black; - border-color: transparent; - color: white; } - .button.is-black[disabled] { - background-color: #0a0a0a; - border-color: transparent; - box-shadow: none; } - .button.is-black.is-inverted { - background-color: white; - color: #0a0a0a; } - .button.is-black.is-inverted:hover { - background-color: #f2f2f2; } - .button.is-black.is-inverted[disabled] { - background-color: white; - border-color: transparent; - box-shadow: none; - color: #0a0a0a; } - .button.is-black.is-loading::after { - border-color: transparent transparent white white !important; } - .button.is-black.is-outlined { - background-color: transparent; - border-color: #0a0a0a; - color: #0a0a0a; } - .button.is-black.is-outlined:hover, .button.is-black.is-outlined:focus { - background-color: #0a0a0a; - border-color: #0a0a0a; - color: white; } - .button.is-black.is-outlined.is-loading::after { - border-color: transparent transparent #0a0a0a #0a0a0a !important; } - .button.is-black.is-outlined[disabled] { - background-color: transparent; - border-color: #0a0a0a; - box-shadow: none; - color: #0a0a0a; } - .button.is-black.is-inverted.is-outlined { - background-color: transparent; - border-color: white; - color: white; } - .button.is-black.is-inverted.is-outlined:hover, .button.is-black.is-inverted.is-outlined:focus { - background-color: white; - color: #0a0a0a; } - .button.is-black.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: white; - box-shadow: none; - color: white; } - .button.is-light { - background-color: whitesmoke; - border-color: transparent; - color: #363636; } - .button.is-light:hover, .button.is-light.is-hovered { - background-color: #eeeeee; - border-color: transparent; - color: #363636; } - .button.is-light:focus, .button.is-light.is-focused { - border-color: transparent; - color: #363636; } - .button.is-light:focus:not(:active), .button.is-light.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); } - .button.is-light:active, .button.is-light.is-active { - background-color: #e8e8e8; - border-color: transparent; - color: #363636; } - .button.is-light[disabled] { - background-color: whitesmoke; - border-color: transparent; - box-shadow: none; } - .button.is-light.is-inverted { - background-color: #363636; - color: whitesmoke; } - .button.is-light.is-inverted:hover { - background-color: #292929; } - .button.is-light.is-inverted[disabled] { - background-color: #363636; - border-color: transparent; - box-shadow: none; - color: whitesmoke; } - .button.is-light.is-loading::after { - border-color: transparent transparent #363636 #363636 !important; } - .button.is-light.is-outlined { - background-color: transparent; - border-color: whitesmoke; - color: whitesmoke; } - .button.is-light.is-outlined:hover, .button.is-light.is-outlined:focus { - background-color: whitesmoke; - border-color: whitesmoke; - color: #363636; } - .button.is-light.is-outlined.is-loading::after { - border-color: transparent transparent whitesmoke whitesmoke !important; } - .button.is-light.is-outlined[disabled] { - background-color: transparent; - border-color: whitesmoke; - box-shadow: none; - color: whitesmoke; } - .button.is-light.is-inverted.is-outlined { - background-color: transparent; - border-color: #363636; - color: #363636; } - .button.is-light.is-inverted.is-outlined:hover, .button.is-light.is-inverted.is-outlined:focus { - background-color: #363636; - color: whitesmoke; } - .button.is-light.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: #363636; - box-shadow: none; - color: #363636; } - .button.is-dark { - background-color: #363636; - border-color: transparent; - color: whitesmoke; } - .button.is-dark:hover, .button.is-dark.is-hovered { - background-color: #2f2f2f; - border-color: transparent; - color: whitesmoke; } - .button.is-dark:focus, .button.is-dark.is-focused { - border-color: transparent; - color: whitesmoke; } - .button.is-dark:focus:not(:active), .button.is-dark.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(54, 54, 54, 0.25); } - .button.is-dark:active, .button.is-dark.is-active { - background-color: #292929; - border-color: transparent; - color: whitesmoke; } - .button.is-dark[disabled] { - background-color: #363636; - border-color: transparent; - box-shadow: none; } - .button.is-dark.is-inverted { - background-color: whitesmoke; - color: #363636; } - .button.is-dark.is-inverted:hover { - background-color: #e8e8e8; } - .button.is-dark.is-inverted[disabled] { - background-color: whitesmoke; - border-color: transparent; - box-shadow: none; - color: #363636; } - .button.is-dark.is-loading::after { - border-color: transparent transparent whitesmoke whitesmoke !important; } - .button.is-dark.is-outlined { - background-color: transparent; - border-color: #363636; - color: #363636; } - .button.is-dark.is-outlined:hover, .button.is-dark.is-outlined:focus { - background-color: #363636; - border-color: #363636; - color: whitesmoke; } - .button.is-dark.is-outlined.is-loading::after { - border-color: transparent transparent #363636 #363636 !important; } - .button.is-dark.is-outlined[disabled] { - background-color: transparent; - border-color: #363636; - box-shadow: none; - color: #363636; } - .button.is-dark.is-inverted.is-outlined { - background-color: transparent; - border-color: whitesmoke; - color: whitesmoke; } - .button.is-dark.is-inverted.is-outlined:hover, .button.is-dark.is-inverted.is-outlined:focus { - background-color: whitesmoke; - color: #363636; } - .button.is-dark.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: whitesmoke; - box-shadow: none; - color: whitesmoke; } - .button.is-primary { - background-color: #00d1b2; - border-color: transparent; - color: #fff; } - .button.is-primary:hover, .button.is-primary.is-hovered { - background-color: #00c4a7; - border-color: transparent; - color: #fff; } - .button.is-primary:focus, .button.is-primary.is-focused { - border-color: transparent; - color: #fff; } - .button.is-primary:focus:not(:active), .button.is-primary.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(0, 209, 178, 0.25); } - .button.is-primary:active, .button.is-primary.is-active { - background-color: #00b89c; - border-color: transparent; - color: #fff; } - .button.is-primary[disabled] { - background-color: #00d1b2; - border-color: transparent; - box-shadow: none; } - .button.is-primary.is-inverted { - background-color: #fff; - color: #00d1b2; } - .button.is-primary.is-inverted:hover { - background-color: #f2f2f2; } - .button.is-primary.is-inverted[disabled] { - background-color: #fff; - border-color: transparent; - box-shadow: none; - color: #00d1b2; } - .button.is-primary.is-loading::after { - border-color: transparent transparent #fff #fff !important; } - .button.is-primary.is-outlined { - background-color: transparent; - border-color: #00d1b2; - color: #00d1b2; } - .button.is-primary.is-outlined:hover, .button.is-primary.is-outlined:focus { - background-color: #00d1b2; - border-color: #00d1b2; - color: #fff; } - .button.is-primary.is-outlined.is-loading::after { - border-color: transparent transparent #00d1b2 #00d1b2 !important; } - .button.is-primary.is-outlined[disabled] { - background-color: transparent; - border-color: #00d1b2; - box-shadow: none; - color: #00d1b2; } - .button.is-primary.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; } - .button.is-primary.is-inverted.is-outlined:hover, .button.is-primary.is-inverted.is-outlined:focus { - background-color: #fff; - color: #00d1b2; } - .button.is-primary.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: #fff; - box-shadow: none; - color: #fff; } - .button.is-link { - background-color: #33B2E8; - border-color: transparent; - color: #fff; } - .button.is-link:hover, .button.is-link.is-hovered { - background-color: #28aee7; - border-color: transparent; - color: #fff; } - .button.is-link:focus, .button.is-link.is-focused { - border-color: transparent; - color: #fff; } - .button.is-link:focus:not(:active), .button.is-link.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(51, 178, 232, 0.25); } - .button.is-link:active, .button.is-link.is-active { - background-color: #1ca9e5; - border-color: transparent; - color: #fff; } - .button.is-link[disabled] { - background-color: #33B2E8; - border-color: transparent; - box-shadow: none; } - .button.is-link.is-inverted { - background-color: #fff; - color: #33B2E8; } - .button.is-link.is-inverted:hover { - background-color: #f2f2f2; } - .button.is-link.is-inverted[disabled] { - background-color: #fff; - border-color: transparent; - box-shadow: none; - color: #33B2E8; } - .button.is-link.is-loading::after { - border-color: transparent transparent #fff #fff !important; } - .button.is-link.is-outlined { - background-color: transparent; - border-color: #33B2E8; - color: #33B2E8; } - .button.is-link.is-outlined:hover, .button.is-link.is-outlined:focus { - background-color: #33B2E8; - border-color: #33B2E8; - color: #fff; } - .button.is-link.is-outlined.is-loading::after { - border-color: transparent transparent #33B2E8 #33B2E8 !important; } - .button.is-link.is-outlined[disabled] { - background-color: transparent; - border-color: #33B2E8; - box-shadow: none; - color: #33B2E8; } - .button.is-link.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; } - .button.is-link.is-inverted.is-outlined:hover, .button.is-link.is-inverted.is-outlined:focus { - background-color: #fff; - color: #33B2E8; } - .button.is-link.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: #fff; - box-shadow: none; - color: #fff; } - .button.is-info { - background-color: #209cee; - border-color: transparent; - color: #fff; } - .button.is-info:hover, .button.is-info.is-hovered { - background-color: #1496ed; - border-color: transparent; - color: #fff; } - .button.is-info:focus, .button.is-info.is-focused { - border-color: transparent; - color: #fff; } - .button.is-info:focus:not(:active), .button.is-info.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(32, 156, 238, 0.25); } - .button.is-info:active, .button.is-info.is-active { - background-color: #118fe4; - border-color: transparent; - color: #fff; } - .button.is-info[disabled] { - background-color: #209cee; - border-color: transparent; - box-shadow: none; } - .button.is-info.is-inverted { - background-color: #fff; - color: #209cee; } - .button.is-info.is-inverted:hover { - background-color: #f2f2f2; } - .button.is-info.is-inverted[disabled] { - background-color: #fff; - border-color: transparent; - box-shadow: none; - color: #209cee; } - .button.is-info.is-loading::after { - border-color: transparent transparent #fff #fff !important; } - .button.is-info.is-outlined { - background-color: transparent; - border-color: #209cee; - color: #209cee; } - .button.is-info.is-outlined:hover, .button.is-info.is-outlined:focus { - background-color: #209cee; - border-color: #209cee; - color: #fff; } - .button.is-info.is-outlined.is-loading::after { - border-color: transparent transparent #209cee #209cee !important; } - .button.is-info.is-outlined[disabled] { - background-color: transparent; - border-color: #209cee; - box-shadow: none; - color: #209cee; } - .button.is-info.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; } - .button.is-info.is-inverted.is-outlined:hover, .button.is-info.is-inverted.is-outlined:focus { - background-color: #fff; - color: #209cee; } - .button.is-info.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: #fff; - box-shadow: none; - color: #fff; } - .button.is-success { - background-color: #23d160; - border-color: transparent; - color: #fff; } - .button.is-success:hover, .button.is-success.is-hovered { - background-color: #22c65b; - border-color: transparent; - color: #fff; } - .button.is-success:focus, .button.is-success.is-focused { - border-color: transparent; - color: #fff; } - .button.is-success:focus:not(:active), .button.is-success.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(35, 209, 96, 0.25); } - .button.is-success:active, .button.is-success.is-active { - background-color: #20bc56; - border-color: transparent; - color: #fff; } - .button.is-success[disabled] { - background-color: #23d160; - border-color: transparent; - box-shadow: none; } - .button.is-success.is-inverted { - background-color: #fff; - color: #23d160; } - .button.is-success.is-inverted:hover { - background-color: #f2f2f2; } - .button.is-success.is-inverted[disabled] { - background-color: #fff; - border-color: transparent; - box-shadow: none; - color: #23d160; } - .button.is-success.is-loading::after { - border-color: transparent transparent #fff #fff !important; } - .button.is-success.is-outlined { - background-color: transparent; - border-color: #23d160; - color: #23d160; } - .button.is-success.is-outlined:hover, .button.is-success.is-outlined:focus { - background-color: #23d160; - border-color: #23d160; - color: #fff; } - .button.is-success.is-outlined.is-loading::after { - border-color: transparent transparent #23d160 #23d160 !important; } - .button.is-success.is-outlined[disabled] { - background-color: transparent; - border-color: #23d160; - box-shadow: none; - color: #23d160; } - .button.is-success.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; } - .button.is-success.is-inverted.is-outlined:hover, .button.is-success.is-inverted.is-outlined:focus { - background-color: #fff; - color: #23d160; } - .button.is-success.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: #fff; - box-shadow: none; - color: #fff; } - .button.is-warning { - background-color: #ffdd57; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); } - .button.is-warning:hover, .button.is-warning.is-hovered { - background-color: #ffdb4a; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); } - .button.is-warning:focus, .button.is-warning.is-focused { - border-color: transparent; - color: rgba(0, 0, 0, 0.7); } - .button.is-warning:focus:not(:active), .button.is-warning.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); } - .button.is-warning:active, .button.is-warning.is-active { - background-color: #ffd83d; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); } - .button.is-warning[disabled] { - background-color: #ffdd57; - border-color: transparent; - box-shadow: none; } - .button.is-warning.is-inverted { - background-color: rgba(0, 0, 0, 0.7); - color: #ffdd57; } - .button.is-warning.is-inverted:hover { - background-color: rgba(0, 0, 0, 0.7); } - .button.is-warning.is-inverted[disabled] { - background-color: rgba(0, 0, 0, 0.7); - border-color: transparent; - box-shadow: none; - color: #ffdd57; } - .button.is-warning.is-loading::after { - border-color: transparent transparent rgba(0, 0, 0, 0.7) rgba(0, 0, 0, 0.7) !important; } - .button.is-warning.is-outlined { - background-color: transparent; - border-color: #ffdd57; - color: #ffdd57; } - .button.is-warning.is-outlined:hover, .button.is-warning.is-outlined:focus { - background-color: #ffdd57; - border-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } - .button.is-warning.is-outlined.is-loading::after { - border-color: transparent transparent #ffdd57 #ffdd57 !important; } - .button.is-warning.is-outlined[disabled] { - background-color: transparent; - border-color: #ffdd57; - box-shadow: none; - color: #ffdd57; } - .button.is-warning.is-inverted.is-outlined { - background-color: transparent; - border-color: rgba(0, 0, 0, 0.7); - color: rgba(0, 0, 0, 0.7); } - .button.is-warning.is-inverted.is-outlined:hover, .button.is-warning.is-inverted.is-outlined:focus { - background-color: rgba(0, 0, 0, 0.7); - color: #ffdd57; } - .button.is-warning.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: rgba(0, 0, 0, 0.7); - box-shadow: none; - color: rgba(0, 0, 0, 0.7); } - .button.is-danger { - background-color: #ff3860; - border-color: transparent; - color: #fff; } - .button.is-danger:hover, .button.is-danger.is-hovered { - background-color: #ff2b56; - border-color: transparent; - color: #fff; } - .button.is-danger:focus, .button.is-danger.is-focused { - border-color: transparent; - color: #fff; } - .button.is-danger:focus:not(:active), .button.is-danger.is-focused:not(:active) { - box-shadow: 0 0 0 0.125em rgba(255, 56, 96, 0.25); } - .button.is-danger:active, .button.is-danger.is-active { - background-color: #ff1f4b; - border-color: transparent; - color: #fff; } - .button.is-danger[disabled] { - background-color: #ff3860; - border-color: transparent; - box-shadow: none; } - .button.is-danger.is-inverted { - background-color: #fff; - color: #ff3860; } - .button.is-danger.is-inverted:hover { - background-color: #f2f2f2; } - .button.is-danger.is-inverted[disabled] { - background-color: #fff; - border-color: transparent; - box-shadow: none; - color: #ff3860; } - .button.is-danger.is-loading::after { - border-color: transparent transparent #fff #fff !important; } - .button.is-danger.is-outlined { - background-color: transparent; - border-color: #ff3860; - color: #ff3860; } - .button.is-danger.is-outlined:hover, .button.is-danger.is-outlined:focus { - background-color: #ff3860; - border-color: #ff3860; - color: #fff; } - .button.is-danger.is-outlined.is-loading::after { - border-color: transparent transparent #ff3860 #ff3860 !important; } - .button.is-danger.is-outlined[disabled] { - background-color: transparent; - border-color: #ff3860; - box-shadow: none; - color: #ff3860; } - .button.is-danger.is-inverted.is-outlined { - background-color: transparent; - border-color: #fff; - color: #fff; } - .button.is-danger.is-inverted.is-outlined:hover, .button.is-danger.is-inverted.is-outlined:focus { - background-color: #fff; - color: #ff3860; } - .button.is-danger.is-inverted.is-outlined[disabled] { - background-color: transparent; - border-color: #fff; - box-shadow: none; - color: #fff; } - .button.is-small { - border-radius: 2px; - font-size: 0.75rem; } - .button.is-medium { - font-size: 1.25rem; } - .button.is-large { - font-size: 1.5rem; } - .button[disabled] { - background-color: white; - border-color: #dbdbdb; - box-shadow: none; - opacity: 0.5; } - .button.is-fullwidth { - display: flex; - width: 100%; } - .button.is-loading { - color: transparent !important; - pointer-events: none; } - .button.is-loading::after { - position: absolute; - left: calc(50% - (1em / 2)); - top: calc(50% - (1em / 2)); - position: absolute !important; } - .button.is-static { - background-color: whitesmoke; - border-color: #dbdbdb; - color: #7a7a7a; - box-shadow: none; - pointer-events: none; } - .button.is-rounded { - border-radius: 290486px; - padding-left: 1em; - padding-right: 1em; } - -.buttons { - align-items: center; - display: flex; - flex-wrap: wrap; - justify-content: flex-start; } - .buttons .button { - margin-bottom: 0.5rem; } - .buttons .button:not(:last-child) { - margin-right: 0.5rem; } - .buttons:last-child { - margin-bottom: -0.5rem; } - .buttons:not(:last-child) { - margin-bottom: 1rem; } - .buttons.has-addons .button:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; } - .buttons.has-addons .button:not(:last-child) { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - margin-right: -1px; } - .buttons.has-addons .button:last-child { - margin-right: 0; } - .buttons.has-addons .button:hover, .buttons.has-addons .button.is-hovered { - z-index: 2; } - .buttons.has-addons .button:focus, .buttons.has-addons .button.is-focused, .buttons.has-addons .button:active, .buttons.has-addons .button.is-active, .buttons.has-addons .button.is-selected { - z-index: 3; } - .buttons.has-addons .button:focus:hover, .buttons.has-addons .button.is-focused:hover, .buttons.has-addons .button:active:hover, .buttons.has-addons .button.is-active:hover, .buttons.has-addons .button.is-selected:hover { - z-index: 4; } - .buttons.has-addons .button.is-expanded { - flex-grow: 1; } - .buttons.is-centered { - justify-content: center; } - .buttons.is-right { - justify-content: flex-end; } - -.container { - margin: 0 auto; - position: relative; } - @media screen and (min-width: 1088px) { - .container { - max-width: 960px; - width: 960px; } - .container.is-fluid { - margin-left: 64px; - margin-right: 64px; - max-width: none; - width: auto; } } - @media screen and (max-width: 1279px) { - .container.is-widescreen { - max-width: 1152px; - width: auto; } } - @media screen and (max-width: 1471px) { - .container.is-fullhd { - max-width: 1344px; - width: auto; } } - @media screen and (min-width: 1280px) { - .container { - max-width: 1152px; - width: 1152px; } } - @media screen and (min-width: 1472px) { - .container { - max-width: 1344px; - width: 1344px; } } - -.content li + li { - margin-top: 0.25em; } - -.content p:not(:last-child), -.content dl:not(:last-child), -.content ol:not(:last-child), -.content ul:not(:last-child), -.content blockquote:not(:last-child), -.content pre:not(:last-child), -.content table:not(:last-child) { - margin-bottom: 1em; } - -.content h1, -.content h2, -.content h3, -.content h4, -.content h5, -.content h6 { - color: #363636; - font-weight: 600; - line-height: 1.125; } - -.content h1 { - font-size: 2em; - margin-bottom: 0.5em; } - .content h1:not(:first-child) { - margin-top: 1em; } - -.content h2 { - font-size: 1.75em; - margin-bottom: 0.5714em; } - .content h2:not(:first-child) { - margin-top: 1.1428em; } - -.content h3 { - font-size: 1.5em; - margin-bottom: 0.6666em; } - .content h3:not(:first-child) { - margin-top: 1.3333em; } - -.content h4 { - font-size: 1.25em; - margin-bottom: 0.8em; } - -.content h5 { - font-size: 1.125em; - margin-bottom: 0.8888em; } - -.content h6 { - font-size: 1em; - margin-bottom: 1em; } - -.content blockquote { - background-color: whitesmoke; - border-left: 5px solid #dbdbdb; - padding: 1.25em 1.5em; } - -.content ol { - list-style: decimal outside; - margin-left: 2em; - margin-top: 1em; } - -.content ul { - list-style: disc outside; - margin-left: 2em; - margin-top: 1em; } - .content ul ul { - list-style-type: circle; - margin-top: 0.5em; } - .content ul ul ul { - list-style-type: square; } - -.content dd { - margin-left: 2em; } - -.content figure { - margin-left: 2em; - margin-right: 2em; - text-align: center; } - .content figure:not(:first-child) { - margin-top: 2em; } - .content figure:not(:last-child) { - margin-bottom: 2em; } - .content figure img { - display: inline-block; } - .content figure figcaption { - font-style: italic; } - -.content pre { - -webkit-overflow-scrolling: touch; - overflow-x: auto; - padding: 1.25em 1.5em; - white-space: pre; - word-wrap: normal; } - -.content sup, -.content sub { - font-size: 75%; } - -.content table { - width: 100%; } - .content table td, - .content table th { - border: 1px solid #dbdbdb; - border-width: 0 0 1px; - padding: 0.5em 0.75em; - vertical-align: top; } - .content table th { - color: #363636; - text-align: left; } - .content table thead td, - .content table thead th { - border-width: 0 0 2px; - color: #363636; } - .content table tfoot td, - .content table tfoot th { - border-width: 2px 0 0; - color: #363636; } - .content table tbody tr:last-child td, - .content table tbody tr:last-child th { - border-bottom-width: 0; } - -.content.is-small { - font-size: 0.75rem; } - -.content.is-medium { - font-size: 1.25rem; } - -.content.is-large { - font-size: 1.5rem; } - -.input, -.textarea { - background-color: white; - border-color: #dbdbdb; - color: #363636; - box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); - max-width: 100%; - width: 100%; } - .input::-moz-placeholder, - .textarea::-moz-placeholder { - color: rgba(54, 54, 54, 0.3); } - .input::-webkit-input-placeholder, - .textarea::-webkit-input-placeholder { - color: rgba(54, 54, 54, 0.3); } - .input:-moz-placeholder, - .textarea:-moz-placeholder { - color: rgba(54, 54, 54, 0.3); } - .input:-ms-input-placeholder, - .textarea:-ms-input-placeholder { - color: rgba(54, 54, 54, 0.3); } - .input:hover, .input.is-hovered, - .textarea:hover, - .textarea.is-hovered { - border-color: #b5b5b5; } - .input:focus, .input.is-focused, .input:active, .input.is-active, - .textarea:focus, - .textarea.is-focused, - .textarea:active, - .textarea.is-active { - border-color: #33B2E8; - box-shadow: 0 0 0 0.125em rgba(51, 178, 232, 0.25); } - .input[disabled], - .textarea[disabled] { - background-color: whitesmoke; - border-color: whitesmoke; - box-shadow: none; - color: #7a7a7a; } - .input[disabled]::-moz-placeholder, - .textarea[disabled]::-moz-placeholder { - color: rgba(122, 122, 122, 0.3); } - .input[disabled]::-webkit-input-placeholder, - .textarea[disabled]::-webkit-input-placeholder { - color: rgba(122, 122, 122, 0.3); } - .input[disabled]:-moz-placeholder, - .textarea[disabled]:-moz-placeholder { - color: rgba(122, 122, 122, 0.3); } - .input[disabled]:-ms-input-placeholder, - .textarea[disabled]:-ms-input-placeholder { - color: rgba(122, 122, 122, 0.3); } - .input[readonly], - .textarea[readonly] { - box-shadow: none; } - .input.is-white, - .textarea.is-white { - border-color: white; } - .input.is-white:focus, .input.is-white.is-focused, .input.is-white:active, .input.is-white.is-active, - .textarea.is-white:focus, - .textarea.is-white.is-focused, - .textarea.is-white:active, - .textarea.is-white.is-active { - box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } - .input.is-black, - .textarea.is-black { - border-color: #0a0a0a; } - .input.is-black:focus, .input.is-black.is-focused, .input.is-black:active, .input.is-black.is-active, - .textarea.is-black:focus, - .textarea.is-black.is-focused, - .textarea.is-black:active, - .textarea.is-black.is-active { - box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } - .input.is-light, - .textarea.is-light { - border-color: whitesmoke; } - .input.is-light:focus, .input.is-light.is-focused, .input.is-light:active, .input.is-light.is-active, - .textarea.is-light:focus, - .textarea.is-light.is-focused, - .textarea.is-light:active, - .textarea.is-light.is-active { - box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); } - .input.is-dark, - .textarea.is-dark { - border-color: #363636; } - .input.is-dark:focus, .input.is-dark.is-focused, .input.is-dark:active, .input.is-dark.is-active, - .textarea.is-dark:focus, - .textarea.is-dark.is-focused, - .textarea.is-dark:active, - .textarea.is-dark.is-active { - box-shadow: 0 0 0 0.125em rgba(54, 54, 54, 0.25); } - .input.is-primary, - .textarea.is-primary { - border-color: #00d1b2; } - .input.is-primary:focus, .input.is-primary.is-focused, .input.is-primary:active, .input.is-primary.is-active, - .textarea.is-primary:focus, - .textarea.is-primary.is-focused, - .textarea.is-primary:active, - .textarea.is-primary.is-active { - box-shadow: 0 0 0 0.125em rgba(0, 209, 178, 0.25); } - .input.is-link, - .textarea.is-link { - border-color: #33B2E8; } - .input.is-link:focus, .input.is-link.is-focused, .input.is-link:active, .input.is-link.is-active, - .textarea.is-link:focus, - .textarea.is-link.is-focused, - .textarea.is-link:active, - .textarea.is-link.is-active { - box-shadow: 0 0 0 0.125em rgba(51, 178, 232, 0.25); } - .input.is-info, - .textarea.is-info { - border-color: #209cee; } - .input.is-info:focus, .input.is-info.is-focused, .input.is-info:active, .input.is-info.is-active, - .textarea.is-info:focus, - .textarea.is-info.is-focused, - .textarea.is-info:active, - .textarea.is-info.is-active { - box-shadow: 0 0 0 0.125em rgba(32, 156, 238, 0.25); } - .input.is-success, - .textarea.is-success { - border-color: #23d160; } - .input.is-success:focus, .input.is-success.is-focused, .input.is-success:active, .input.is-success.is-active, - .textarea.is-success:focus, - .textarea.is-success.is-focused, - .textarea.is-success:active, - .textarea.is-success.is-active { - box-shadow: 0 0 0 0.125em rgba(35, 209, 96, 0.25); } - .input.is-warning, - .textarea.is-warning { - border-color: #ffdd57; } - .input.is-warning:focus, .input.is-warning.is-focused, .input.is-warning:active, .input.is-warning.is-active, - .textarea.is-warning:focus, - .textarea.is-warning.is-focused, - .textarea.is-warning:active, - .textarea.is-warning.is-active { - box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); } - .input.is-danger, - .textarea.is-danger { - border-color: #ff3860; } - .input.is-danger:focus, .input.is-danger.is-focused, .input.is-danger:active, .input.is-danger.is-active, - .textarea.is-danger:focus, - .textarea.is-danger.is-focused, - .textarea.is-danger:active, - .textarea.is-danger.is-active { - box-shadow: 0 0 0 0.125em rgba(255, 56, 96, 0.25); } - .input.is-small, - .textarea.is-small { - border-radius: 2px; - font-size: 0.75rem; } - .input.is-medium, - .textarea.is-medium { - font-size: 1.25rem; } - .input.is-large, - .textarea.is-large { - font-size: 1.5rem; } - .input.is-fullwidth, - .textarea.is-fullwidth { - display: block; - width: 100%; } - .input.is-inline, - .textarea.is-inline { - display: inline; - width: auto; } - -.input.is-rounded { - border-radius: 290486px; - padding-left: 1em; - padding-right: 1em; } - -.input.is-static { - background-color: transparent; - border-color: transparent; - box-shadow: none; - padding-left: 0; - padding-right: 0; } - -.textarea { - display: block; - max-width: 100%; - min-width: 100%; - padding: 0.625em; - resize: vertical; } - .textarea:not([rows]) { - max-height: 600px; - min-height: 120px; } - .textarea[rows] { - height: initial; } - .textarea.has-fixed-size { - resize: none; } - -.checkbox, -.radio { - cursor: pointer; - display: inline-block; - line-height: 1.25; - position: relative; } - .checkbox input, - .radio input { - cursor: pointer; } - .checkbox:hover, - .radio:hover { - color: #363636; } - .checkbox[disabled], - .radio[disabled] { - color: #7a7a7a; - cursor: not-allowed; } - -.radio + .radio { - margin-left: 0.5em; } - -.select { - display: inline-block; - max-width: 100%; - position: relative; - vertical-align: top; } - .select:not(.is-multiple) { - height: 2.25em; } - .select:not(.is-multiple):not(.is-loading)::after { - border-color: #33B2E8; - right: 1.125em; - z-index: 4; } - .select.is-rounded select { - border-radius: 290486px; - padding-left: 1em; } - .select select { - background-color: white; - border-color: #dbdbdb; - color: #363636; - cursor: pointer; - display: block; - font-size: 1em; - max-width: 100%; - outline: none; } - .select select::-moz-placeholder { - color: rgba(54, 54, 54, 0.3); } - .select select::-webkit-input-placeholder { - color: rgba(54, 54, 54, 0.3); } - .select select:-moz-placeholder { - color: rgba(54, 54, 54, 0.3); } - .select select:-ms-input-placeholder { - color: rgba(54, 54, 54, 0.3); } - .select select:hover, .select select.is-hovered { - border-color: #b5b5b5; } - .select select:focus, .select select.is-focused, .select select:active, .select select.is-active { - border-color: #33B2E8; - box-shadow: 0 0 0 0.125em rgba(51, 178, 232, 0.25); } - .select select[disabled] { - background-color: whitesmoke; - border-color: whitesmoke; - box-shadow: none; - color: #7a7a7a; } - .select select[disabled]::-moz-placeholder { - color: rgba(122, 122, 122, 0.3); } - .select select[disabled]::-webkit-input-placeholder { - color: rgba(122, 122, 122, 0.3); } - .select select[disabled]:-moz-placeholder { - color: rgba(122, 122, 122, 0.3); } - .select select[disabled]:-ms-input-placeholder { - color: rgba(122, 122, 122, 0.3); } - .select select::-ms-expand { - display: none; } - .select select[disabled]:hover { - border-color: whitesmoke; } - .select select:not([multiple]) { - padding-right: 2.5em; } - .select select[multiple] { - height: initial; - padding: 0; } - .select select[multiple] option { - padding: 0.5em 1em; } - .select:not(.is-multiple):not(.is-loading):hover::after { - border-color: #363636; } - .select.is-white:not(:hover)::after { - border-color: white; } - .select.is-white select { - border-color: white; } - .select.is-white select:hover, .select.is-white select.is-hovered { - border-color: #f2f2f2; } - .select.is-white select:focus, .select.is-white select.is-focused, .select.is-white select:active, .select.is-white select.is-active { - box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25); } - .select.is-black:not(:hover)::after { - border-color: #0a0a0a; } - .select.is-black select { - border-color: #0a0a0a; } - .select.is-black select:hover, .select.is-black select.is-hovered { - border-color: black; } - .select.is-black select:focus, .select.is-black select.is-focused, .select.is-black select:active, .select.is-black select.is-active { - box-shadow: 0 0 0 0.125em rgba(10, 10, 10, 0.25); } - .select.is-light:not(:hover)::after { - border-color: whitesmoke; } - .select.is-light select { - border-color: whitesmoke; } - .select.is-light select:hover, .select.is-light select.is-hovered { - border-color: #e8e8e8; } - .select.is-light select:focus, .select.is-light select.is-focused, .select.is-light select:active, .select.is-light select.is-active { - box-shadow: 0 0 0 0.125em rgba(245, 245, 245, 0.25); } - .select.is-dark:not(:hover)::after { - border-color: #363636; } - .select.is-dark select { - border-color: #363636; } - .select.is-dark select:hover, .select.is-dark select.is-hovered { - border-color: #292929; } - .select.is-dark select:focus, .select.is-dark select.is-focused, .select.is-dark select:active, .select.is-dark select.is-active { - box-shadow: 0 0 0 0.125em rgba(54, 54, 54, 0.25); } - .select.is-primary:not(:hover)::after { - border-color: #00d1b2; } - .select.is-primary select { - border-color: #00d1b2; } - .select.is-primary select:hover, .select.is-primary select.is-hovered { - border-color: #00b89c; } - .select.is-primary select:focus, .select.is-primary select.is-focused, .select.is-primary select:active, .select.is-primary select.is-active { - box-shadow: 0 0 0 0.125em rgba(0, 209, 178, 0.25); } - .select.is-link:not(:hover)::after { - border-color: #33B2E8; } - .select.is-link select { - border-color: #33B2E8; } - .select.is-link select:hover, .select.is-link select.is-hovered { - border-color: #1ca9e5; } - .select.is-link select:focus, .select.is-link select.is-focused, .select.is-link select:active, .select.is-link select.is-active { - box-shadow: 0 0 0 0.125em rgba(51, 178, 232, 0.25); } - .select.is-info:not(:hover)::after { - border-color: #209cee; } - .select.is-info select { - border-color: #209cee; } - .select.is-info select:hover, .select.is-info select.is-hovered { - border-color: #118fe4; } - .select.is-info select:focus, .select.is-info select.is-focused, .select.is-info select:active, .select.is-info select.is-active { - box-shadow: 0 0 0 0.125em rgba(32, 156, 238, 0.25); } - .select.is-success:not(:hover)::after { - border-color: #23d160; } - .select.is-success select { - border-color: #23d160; } - .select.is-success select:hover, .select.is-success select.is-hovered { - border-color: #20bc56; } - .select.is-success select:focus, .select.is-success select.is-focused, .select.is-success select:active, .select.is-success select.is-active { - box-shadow: 0 0 0 0.125em rgba(35, 209, 96, 0.25); } - .select.is-warning:not(:hover)::after { - border-color: #ffdd57; } - .select.is-warning select { - border-color: #ffdd57; } - .select.is-warning select:hover, .select.is-warning select.is-hovered { - border-color: #ffd83d; } - .select.is-warning select:focus, .select.is-warning select.is-focused, .select.is-warning select:active, .select.is-warning select.is-active { - box-shadow: 0 0 0 0.125em rgba(255, 221, 87, 0.25); } - .select.is-danger:not(:hover)::after { - border-color: #ff3860; } - .select.is-danger select { - border-color: #ff3860; } - .select.is-danger select:hover, .select.is-danger select.is-hovered { - border-color: #ff1f4b; } - .select.is-danger select:focus, .select.is-danger select.is-focused, .select.is-danger select:active, .select.is-danger select.is-active { - box-shadow: 0 0 0 0.125em rgba(255, 56, 96, 0.25); } - .select.is-small { - border-radius: 2px; - font-size: 0.75rem; } - .select.is-medium { - font-size: 1.25rem; } - .select.is-large { - font-size: 1.5rem; } - .select.is-disabled::after { - border-color: #7a7a7a; } - .select.is-fullwidth { - width: 100%; } - .select.is-fullwidth select { - width: 100%; } - .select.is-loading::after { - margin-top: 0; - position: absolute; - right: 0.625em; - top: 0.625em; - transform: none; } - .select.is-loading.is-small:after { - font-size: 0.75rem; } - .select.is-loading.is-medium:after { - font-size: 1.25rem; } - .select.is-loading.is-large:after { - font-size: 1.5rem; } - -.file { - align-items: stretch; - display: flex; - justify-content: flex-start; - position: relative; } - .file.is-white .file-cta { - background-color: white; - border-color: transparent; - color: #0a0a0a; } - .file.is-white:hover .file-cta, .file.is-white.is-hovered .file-cta { - background-color: #f9f9f9; - border-color: transparent; - color: #0a0a0a; } - .file.is-white:focus .file-cta, .file.is-white.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(255, 255, 255, 0.25); - color: #0a0a0a; } - .file.is-white:active .file-cta, .file.is-white.is-active .file-cta { - background-color: #f2f2f2; - border-color: transparent; - color: #0a0a0a; } - .file.is-black .file-cta { - background-color: #0a0a0a; - border-color: transparent; - color: white; } - .file.is-black:hover .file-cta, .file.is-black.is-hovered .file-cta { - background-color: #040404; - border-color: transparent; - color: white; } - .file.is-black:focus .file-cta, .file.is-black.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(10, 10, 10, 0.25); - color: white; } - .file.is-black:active .file-cta, .file.is-black.is-active .file-cta { - background-color: black; - border-color: transparent; - color: white; } - .file.is-light .file-cta { - background-color: whitesmoke; - border-color: transparent; - color: #363636; } - .file.is-light:hover .file-cta, .file.is-light.is-hovered .file-cta { - background-color: #eeeeee; - border-color: transparent; - color: #363636; } - .file.is-light:focus .file-cta, .file.is-light.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(245, 245, 245, 0.25); - color: #363636; } - .file.is-light:active .file-cta, .file.is-light.is-active .file-cta { - background-color: #e8e8e8; - border-color: transparent; - color: #363636; } - .file.is-dark .file-cta { - background-color: #363636; - border-color: transparent; - color: whitesmoke; } - .file.is-dark:hover .file-cta, .file.is-dark.is-hovered .file-cta { - background-color: #2f2f2f; - border-color: transparent; - color: whitesmoke; } - .file.is-dark:focus .file-cta, .file.is-dark.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(54, 54, 54, 0.25); - color: whitesmoke; } - .file.is-dark:active .file-cta, .file.is-dark.is-active .file-cta { - background-color: #292929; - border-color: transparent; - color: whitesmoke; } - .file.is-primary .file-cta { - background-color: #00d1b2; - border-color: transparent; - color: #fff; } - .file.is-primary:hover .file-cta, .file.is-primary.is-hovered .file-cta { - background-color: #00c4a7; - border-color: transparent; - color: #fff; } - .file.is-primary:focus .file-cta, .file.is-primary.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(0, 209, 178, 0.25); - color: #fff; } - .file.is-primary:active .file-cta, .file.is-primary.is-active .file-cta { - background-color: #00b89c; - border-color: transparent; - color: #fff; } - .file.is-link .file-cta { - background-color: #33B2E8; - border-color: transparent; - color: #fff; } - .file.is-link:hover .file-cta, .file.is-link.is-hovered .file-cta { - background-color: #28aee7; - border-color: transparent; - color: #fff; } - .file.is-link:focus .file-cta, .file.is-link.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(51, 178, 232, 0.25); - color: #fff; } - .file.is-link:active .file-cta, .file.is-link.is-active .file-cta { - background-color: #1ca9e5; - border-color: transparent; - color: #fff; } - .file.is-info .file-cta { - background-color: #209cee; - border-color: transparent; - color: #fff; } - .file.is-info:hover .file-cta, .file.is-info.is-hovered .file-cta { - background-color: #1496ed; - border-color: transparent; - color: #fff; } - .file.is-info:focus .file-cta, .file.is-info.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(32, 156, 238, 0.25); - color: #fff; } - .file.is-info:active .file-cta, .file.is-info.is-active .file-cta { - background-color: #118fe4; - border-color: transparent; - color: #fff; } - .file.is-success .file-cta { - background-color: #23d160; - border-color: transparent; - color: #fff; } - .file.is-success:hover .file-cta, .file.is-success.is-hovered .file-cta { - background-color: #22c65b; - border-color: transparent; - color: #fff; } - .file.is-success:focus .file-cta, .file.is-success.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(35, 209, 96, 0.25); - color: #fff; } - .file.is-success:active .file-cta, .file.is-success.is-active .file-cta { - background-color: #20bc56; - border-color: transparent; - color: #fff; } - .file.is-warning .file-cta { - background-color: #ffdd57; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); } - .file.is-warning:hover .file-cta, .file.is-warning.is-hovered .file-cta { - background-color: #ffdb4a; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); } - .file.is-warning:focus .file-cta, .file.is-warning.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(255, 221, 87, 0.25); - color: rgba(0, 0, 0, 0.7); } - .file.is-warning:active .file-cta, .file.is-warning.is-active .file-cta { - background-color: #ffd83d; - border-color: transparent; - color: rgba(0, 0, 0, 0.7); } - .file.is-danger .file-cta { - background-color: #ff3860; - border-color: transparent; - color: #fff; } - .file.is-danger:hover .file-cta, .file.is-danger.is-hovered .file-cta { - background-color: #ff2b56; - border-color: transparent; - color: #fff; } - .file.is-danger:focus .file-cta, .file.is-danger.is-focused .file-cta { - border-color: transparent; - box-shadow: 0 0 0.5em rgba(255, 56, 96, 0.25); - color: #fff; } - .file.is-danger:active .file-cta, .file.is-danger.is-active .file-cta { - background-color: #ff1f4b; - border-color: transparent; - color: #fff; } - .file.is-small { - font-size: 0.75rem; } - .file.is-medium { - font-size: 1.25rem; } - .file.is-medium .file-icon .fa { - font-size: 21px; } - .file.is-large { - font-size: 1.5rem; } - .file.is-large .file-icon .fa { - font-size: 28px; } - .file.has-name .file-cta { - border-bottom-right-radius: 0; - border-top-right-radius: 0; } - .file.has-name .file-name { - border-bottom-left-radius: 0; - border-top-left-radius: 0; } - .file.has-name.is-empty .file-cta { - border-radius: 4px; } - .file.has-name.is-empty .file-name { - display: none; } - .file.is-boxed .file-label { - flex-direction: column; } - .file.is-boxed .file-cta { - flex-direction: column; - height: auto; - padding: 1em 3em; } - .file.is-boxed .file-name { - border-width: 0 1px 1px; } - .file.is-boxed .file-icon { - height: 1.5em; - width: 1.5em; } - .file.is-boxed .file-icon .fa { - font-size: 21px; } - .file.is-boxed.is-small .file-icon .fa { - font-size: 14px; } - .file.is-boxed.is-medium .file-icon .fa { - font-size: 28px; } - .file.is-boxed.is-large .file-icon .fa { - font-size: 35px; } - .file.is-boxed.has-name .file-cta { - border-radius: 4px 4px 0 0; } - .file.is-boxed.has-name .file-name { - border-radius: 0 0 4px 4px; - border-width: 0 1px 1px; } - .file.is-centered { - justify-content: center; } - .file.is-fullwidth .file-label { - width: 100%; } - .file.is-fullwidth .file-name { - flex-grow: 1; - max-width: none; } - .file.is-right { - justify-content: flex-end; } - .file.is-right .file-cta { - border-radius: 0 4px 4px 0; } - .file.is-right .file-name { - border-radius: 4px 0 0 4px; - border-width: 1px 0 1px 1px; - order: -1; } - -.file-label { - align-items: stretch; - display: flex; - cursor: pointer; - justify-content: flex-start; - overflow: hidden; - position: relative; } - .file-label:hover .file-cta { - background-color: #eeeeee; - color: #363636; } - .file-label:hover .file-name { - border-color: #d5d5d5; } - .file-label:active .file-cta { - background-color: #e8e8e8; - color: #363636; } - .file-label:active .file-name { - border-color: #cfcfcf; } - -.file-input { - height: 0.01em; - left: 0; - outline: none; - position: absolute; - top: 0; - width: 0.01em; } - -.file-cta, -.file-name { - border-color: #dbdbdb; - border-radius: 4px; - font-size: 1em; - padding-left: 1em; - padding-right: 1em; - white-space: nowrap; } - -.file-cta { - background-color: whitesmoke; - color: #4a4a4a; } - -.file-name { - border-color: #dbdbdb; - border-style: solid; - border-width: 1px 1px 1px 0; - display: block; - max-width: 16em; - overflow: hidden; - text-align: left; - text-overflow: ellipsis; } - -.file-icon { - align-items: center; - display: flex; - height: 1em; - justify-content: center; - margin-right: 0.5em; - width: 1em; } - .file-icon .fa { - font-size: 14px; } - -.label { - color: #363636; - display: block; - font-size: 1rem; - font-weight: 700; } - .label:not(:last-child) { - margin-bottom: 0.5em; } - .label.is-small { - font-size: 0.75rem; } - .label.is-medium { - font-size: 1.25rem; } - .label.is-large { - font-size: 1.5rem; } - -.help { - display: block; - font-size: 0.75rem; - margin-top: 0.25rem; } - .help.is-white { - color: white; } - .help.is-black { - color: #0a0a0a; } - .help.is-light { - color: whitesmoke; } - .help.is-dark { - color: #363636; } - .help.is-primary { - color: #00d1b2; } - .help.is-link { - color: #33B2E8; } - .help.is-info { - color: #209cee; } - .help.is-success { - color: #23d160; } - .help.is-warning { - color: #ffdd57; } - .help.is-danger { - color: #ff3860; } - -.field:not(:last-child) { - margin-bottom: 0.75rem; } - -.field.has-addons { - display: flex; - justify-content: flex-start; } - .field.has-addons .control:not(:last-child) { - margin-right: -1px; } - .field.has-addons .control:not(:first-child):not(:last-child) .button, - .field.has-addons .control:not(:first-child):not(:last-child) .input, - .field.has-addons .control:not(:first-child):not(:last-child) .select select { - border-radius: 0; } - .field.has-addons .control:first-child .button, - .field.has-addons .control:first-child .input, - .field.has-addons .control:first-child .select select { - border-bottom-right-radius: 0; - border-top-right-radius: 0; } - .field.has-addons .control:last-child .button, - .field.has-addons .control:last-child .input, - .field.has-addons .control:last-child .select select { - border-bottom-left-radius: 0; - border-top-left-radius: 0; } - .field.has-addons .control .button:hover, .field.has-addons .control .button.is-hovered, - .field.has-addons .control .input:hover, - .field.has-addons .control .input.is-hovered, - .field.has-addons .control .select select:hover, - .field.has-addons .control .select select.is-hovered { - z-index: 2; } - .field.has-addons .control .button:focus, .field.has-addons .control .button.is-focused, .field.has-addons .control .button:active, .field.has-addons .control .button.is-active, - .field.has-addons .control .input:focus, - .field.has-addons .control .input.is-focused, - .field.has-addons .control .input:active, - .field.has-addons .control .input.is-active, - .field.has-addons .control .select select:focus, - .field.has-addons .control .select select.is-focused, - .field.has-addons .control .select select:active, - .field.has-addons .control .select select.is-active { - z-index: 3; } - .field.has-addons .control .button:focus:hover, .field.has-addons .control .button.is-focused:hover, .field.has-addons .control .button:active:hover, .field.has-addons .control .button.is-active:hover, - .field.has-addons .control .input:focus:hover, - .field.has-addons .control .input.is-focused:hover, - .field.has-addons .control .input:active:hover, - .field.has-addons .control .input.is-active:hover, - .field.has-addons .control .select select:focus:hover, - .field.has-addons .control .select select.is-focused:hover, - .field.has-addons .control .select select:active:hover, - .field.has-addons .control .select select.is-active:hover { - z-index: 4; } - .field.has-addons .control.is-expanded { - flex-grow: 1; } - .field.has-addons.has-addons-centered { - justify-content: center; } - .field.has-addons.has-addons-right { - justify-content: flex-end; } - .field.has-addons.has-addons-fullwidth .control { - flex-grow: 1; - flex-shrink: 0; } - -.field.is-grouped { - display: flex; - justify-content: flex-start; } - .field.is-grouped > .control { - flex-shrink: 0; } - .field.is-grouped > .control:not(:last-child) { - margin-bottom: 0; - margin-right: 0.75rem; } - .field.is-grouped > .control.is-expanded { - flex-grow: 1; - flex-shrink: 1; } - .field.is-grouped.is-grouped-centered { - justify-content: center; } - .field.is-grouped.is-grouped-right { - justify-content: flex-end; } - .field.is-grouped.is-grouped-multiline { - flex-wrap: wrap; } - .field.is-grouped.is-grouped-multiline > .control:last-child, .field.is-grouped.is-grouped-multiline > .control:not(:last-child) { - margin-bottom: 0.75rem; } - .field.is-grouped.is-grouped-multiline:last-child { - margin-bottom: -0.75rem; } - .field.is-grouped.is-grouped-multiline:not(:last-child) { - margin-bottom: 0; } - -@media screen and (min-width: 769px), print { - .field.is-horizontal { - display: flex; } } - -.field-label .label { - font-size: inherit; } - -@media screen and (max-width: 768px) { - .field-label { - margin-bottom: 0.5rem; } } - -@media screen and (min-width: 769px), print { - .field-label { - flex-basis: 0; - flex-grow: 1; - flex-shrink: 0; - margin-right: 1.5rem; - text-align: right; } - .field-label.is-small { - font-size: 0.75rem; - padding-top: 0.375em; } - .field-label.is-normal { - padding-top: 0.375em; } - .field-label.is-medium { - font-size: 1.25rem; - padding-top: 0.375em; } - .field-label.is-large { - font-size: 1.5rem; - padding-top: 0.375em; } } - -.field-body .field .field { - margin-bottom: 0; } - -@media screen and (min-width: 769px), print { - .field-body { - display: flex; - flex-basis: 0; - flex-grow: 5; - flex-shrink: 1; } - .field-body .field { - margin-bottom: 0; } - .field-body > .field { - flex-shrink: 1; } - .field-body > .field:not(.is-narrow) { - flex-grow: 1; } - .field-body > .field:not(:last-child) { - margin-right: 0.75rem; } } - -.control { - font-size: 1rem; - position: relative; - text-align: left; } - .control.has-icon .icon { - color: #dbdbdb; - height: 2.25em; - pointer-events: none; - position: absolute; - top: 0; - width: 2.25em; - z-index: 4; } - .control.has-icon .input:focus + .icon { - color: #7a7a7a; } - .control.has-icon .input.is-small + .icon { - font-size: 0.75rem; } - .control.has-icon .input.is-medium + .icon { - font-size: 1.25rem; } - .control.has-icon .input.is-large + .icon { - font-size: 1.5rem; } - .control.has-icon:not(.has-icon-right) .icon { - left: 0; } - .control.has-icon:not(.has-icon-right) .input { - padding-left: 2.25em; } - .control.has-icon.has-icon-right .icon { - right: 0; } - .control.has-icon.has-icon-right .input { - padding-right: 2.25em; } - .control.has-icons-left .input:focus ~ .icon, - .control.has-icons-left .select:focus ~ .icon, .control.has-icons-right .input:focus ~ .icon, - .control.has-icons-right .select:focus ~ .icon { - color: #7a7a7a; } - .control.has-icons-left .input.is-small ~ .icon, - .control.has-icons-left .select.is-small ~ .icon, .control.has-icons-right .input.is-small ~ .icon, - .control.has-icons-right .select.is-small ~ .icon { - font-size: 0.75rem; } - .control.has-icons-left .input.is-medium ~ .icon, - .control.has-icons-left .select.is-medium ~ .icon, .control.has-icons-right .input.is-medium ~ .icon, - .control.has-icons-right .select.is-medium ~ .icon { - font-size: 1.25rem; } - .control.has-icons-left .input.is-large ~ .icon, - .control.has-icons-left .select.is-large ~ .icon, .control.has-icons-right .input.is-large ~ .icon, - .control.has-icons-right .select.is-large ~ .icon { - font-size: 1.5rem; } - .control.has-icons-left .icon, .control.has-icons-right .icon { - color: #dbdbdb; - height: 2.25em; - pointer-events: none; - position: absolute; - top: 0; - width: 2.25em; - z-index: 4; } - .control.has-icons-left .input, - .control.has-icons-left .select select { - padding-left: 2.25em; } - .control.has-icons-left .icon.is-left { - left: 0; } - .control.has-icons-right .input, - .control.has-icons-right .select select { - padding-right: 2.25em; } - .control.has-icons-right .icon.is-right { - right: 0; } - .control.is-loading::after { - position: absolute !important; - right: 0.625em; - top: 0.625em; - z-index: 4; } - .control.is-loading.is-small:after { - font-size: 0.75rem; } - .control.is-loading.is-medium:after { - font-size: 1.25rem; } - .control.is-loading.is-large:after { - font-size: 1.5rem; } - -.icon { - align-items: center; - display: inline-flex; - justify-content: center; - height: 1.5rem; - width: 1.5rem; } - .icon.is-small { - height: 1rem; - width: 1rem; } - .icon.is-medium { - height: 2rem; - width: 2rem; } - .icon.is-large { - height: 3rem; - width: 3rem; } - -.image { - display: block; - position: relative; } - .image img { - display: block; - height: auto; - width: 100%; } - .image img.is-rounded { - border-radius: 290486px; } - .image.is-square img, .image.is-1by1 img, .image.is-5by4 img, .image.is-4by3 img, .image.is-3by2 img, .image.is-5by3 img, .image.is-16by9 img, .image.is-2by1 img, .image.is-3by1 img, .image.is-4by5 img, .image.is-3by4 img, .image.is-2by3 img, .image.is-3by5 img, .image.is-9by16 img, .image.is-1by2 img, .image.is-1by3 img { - height: 100%; - width: 100%; } - .image.is-square, .image.is-1by1 { - padding-top: 100%; } - .image.is-5by4 { - padding-top: 80%; } - .image.is-4by3 { - padding-top: 75%; } - .image.is-3by2 { - padding-top: 66.6666%; } - .image.is-5by3 { - padding-top: 60%; } - .image.is-16by9 { - padding-top: 56.25%; } - .image.is-2by1 { - padding-top: 50%; } - .image.is-3by1 { - padding-top: 33.3333%; } - .image.is-4by5 { - padding-top: 125%; } - .image.is-3by4 { - padding-top: 133.3333%; } - .image.is-2by3 { - padding-top: 150%; } - .image.is-3by5 { - padding-top: 166.6666%; } - .image.is-9by16 { - padding-top: 177.7777%; } - .image.is-1by2 { - padding-top: 200%; } - .image.is-1by3 { - padding-top: 300%; } - .image.is-16x16 { - height: 16px; - width: 16px; } - .image.is-24x24 { - height: 24px; - width: 24px; } - .image.is-32x32 { - height: 32px; - width: 32px; } - .image.is-48x48 { - height: 48px; - width: 48px; } - .image.is-64x64 { - height: 64px; - width: 64px; } - .image.is-96x96 { - height: 96px; - width: 96px; } - .image.is-128x128 { - height: 128px; - width: 128px; } - -.notification { - background-color: whitesmoke; - border-radius: 4px; - padding: 1.25rem 2.5rem 1.25rem 1.5rem; - position: relative; } - .notification a:not(.button) { - color: currentColor; - text-decoration: underline; } - .notification strong { - color: currentColor; } - .notification code, - .notification pre { - background: white; } - .notification pre code { - background: transparent; } - .notification > .delete { - position: absolute; - right: 0.5rem; - top: 0.5rem; } - .notification .title, - .notification .subtitle, - .notification .content { - color: currentColor; } - .notification.is-white { - background-color: white; - color: #0a0a0a; } - .notification.is-black { - background-color: #0a0a0a; - color: white; } - .notification.is-light { - background-color: whitesmoke; - color: #363636; } - .notification.is-dark { - background-color: #363636; - color: whitesmoke; } - .notification.is-primary { - background-color: #00d1b2; - color: #fff; } - .notification.is-link { - background-color: #33B2E8; - color: #fff; } - .notification.is-info { - background-color: #209cee; - color: #fff; } - .notification.is-success { - background-color: #23d160; - color: #fff; } - .notification.is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } - .notification.is-danger { - background-color: #ff3860; - color: #fff; } - -.progress { - -moz-appearance: none; - -webkit-appearance: none; - border: none; - border-radius: 290486px; - display: block; - height: 1rem; - overflow: hidden; - padding: 0; - width: 100%; } - .progress::-webkit-progress-bar { - background-color: #dbdbdb; } - .progress::-webkit-progress-value { - background-color: #4a4a4a; } - .progress::-moz-progress-bar { - background-color: #4a4a4a; } - .progress::-ms-fill { - background-color: #4a4a4a; - border: none; } - .progress.is-white::-webkit-progress-value { - background-color: white; } - .progress.is-white::-moz-progress-bar { - background-color: white; } - .progress.is-white::-ms-fill { - background-color: white; } - .progress.is-black::-webkit-progress-value { - background-color: #0a0a0a; } - .progress.is-black::-moz-progress-bar { - background-color: #0a0a0a; } - .progress.is-black::-ms-fill { - background-color: #0a0a0a; } - .progress.is-light::-webkit-progress-value { - background-color: whitesmoke; } - .progress.is-light::-moz-progress-bar { - background-color: whitesmoke; } - .progress.is-light::-ms-fill { - background-color: whitesmoke; } - .progress.is-dark::-webkit-progress-value { - background-color: #363636; } - .progress.is-dark::-moz-progress-bar { - background-color: #363636; } - .progress.is-dark::-ms-fill { - background-color: #363636; } - .progress.is-primary::-webkit-progress-value { - background-color: #00d1b2; } - .progress.is-primary::-moz-progress-bar { - background-color: #00d1b2; } - .progress.is-primary::-ms-fill { - background-color: #00d1b2; } - .progress.is-link::-webkit-progress-value { - background-color: #33B2E8; } - .progress.is-link::-moz-progress-bar { - background-color: #33B2E8; } - .progress.is-link::-ms-fill { - background-color: #33B2E8; } - .progress.is-info::-webkit-progress-value { - background-color: #209cee; } - .progress.is-info::-moz-progress-bar { - background-color: #209cee; } - .progress.is-info::-ms-fill { - background-color: #209cee; } - .progress.is-success::-webkit-progress-value { - background-color: #23d160; } - .progress.is-success::-moz-progress-bar { - background-color: #23d160; } - .progress.is-success::-ms-fill { - background-color: #23d160; } - .progress.is-warning::-webkit-progress-value { - background-color: #ffdd57; } - .progress.is-warning::-moz-progress-bar { - background-color: #ffdd57; } - .progress.is-warning::-ms-fill { - background-color: #ffdd57; } - .progress.is-danger::-webkit-progress-value { - background-color: #ff3860; } - .progress.is-danger::-moz-progress-bar { - background-color: #ff3860; } - .progress.is-danger::-ms-fill { - background-color: #ff3860; } - .progress.is-small { - height: 0.75rem; } - .progress.is-medium { - height: 1.25rem; } - .progress.is-large { - height: 1.5rem; } - -.table { - background-color: white; - color: #363636; } - .table td, - .table th { - border: 1px solid #dbdbdb; - border-width: 0 0 1px; - padding: 0.5em 0.75em; - vertical-align: top; } - .table td.is-white, - .table th.is-white { - background-color: white; - border-color: white; - color: #0a0a0a; } - .table td.is-black, - .table th.is-black { - background-color: #0a0a0a; - border-color: #0a0a0a; - color: white; } - .table td.is-light, - .table th.is-light { - background-color: whitesmoke; - border-color: whitesmoke; - color: #363636; } - .table td.is-dark, - .table th.is-dark { - background-color: #363636; - border-color: #363636; - color: whitesmoke; } - .table td.is-primary, - .table th.is-primary { - background-color: #00d1b2; - border-color: #00d1b2; - color: #fff; } - .table td.is-link, - .table th.is-link { - background-color: #33B2E8; - border-color: #33B2E8; - color: #fff; } - .table td.is-info, - .table th.is-info { - background-color: #209cee; - border-color: #209cee; - color: #fff; } - .table td.is-success, - .table th.is-success { - background-color: #23d160; - border-color: #23d160; - color: #fff; } - .table td.is-warning, - .table th.is-warning { - background-color: #ffdd57; - border-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } - .table td.is-danger, - .table th.is-danger { - background-color: #ff3860; - border-color: #ff3860; - color: #fff; } - .table td.is-narrow, - .table th.is-narrow { - white-space: nowrap; - width: 1%; } - .table td.is-selected, - .table th.is-selected { - background-color: #00d1b2; - color: #fff; } - .table td.is-selected a, - .table td.is-selected strong, - .table th.is-selected a, - .table th.is-selected strong { - color: currentColor; } - .table th { - color: #363636; - text-align: left; } - .table tr.is-selected { - background-color: #00d1b2; - color: #fff; } - .table tr.is-selected a, - .table tr.is-selected strong { - color: currentColor; } - .table tr.is-selected td, - .table tr.is-selected th { - border-color: #fff; - color: currentColor; } - .table thead td, - .table thead th { - border-width: 0 0 2px; - color: #363636; } - .table tfoot td, - .table tfoot th { - border-width: 2px 0 0; - color: #363636; } - .table tbody tr:last-child td, - .table tbody tr:last-child th { - border-bottom-width: 0; } - .table.is-bordered td, - .table.is-bordered th { - border-width: 1px; } - .table.is-bordered tr:last-child td, - .table.is-bordered tr:last-child th { - border-bottom-width: 1px; } - .table.is-fullwidth { - width: 100%; } - .table.is-hoverable tbody tr:not(.is-selected):hover { - background-color: #fafafa; } - .table.is-hoverable.is-striped tbody tr:not(.is-selected):hover { - background-color: whitesmoke; } - .table.is-narrow td, - .table.is-narrow th { - padding: 0.25em 0.5em; } - .table.is-striped tbody tr:not(.is-selected):nth-child(even) { - background-color: #fafafa; } - -.table-container { - -webkit-overflow-scrolling: touch; - overflow: auto; - overflow-y: hidden; - max-width: 100%; } - -.tags { - align-items: center; - display: flex; - flex-wrap: wrap; - justify-content: flex-start; } - .tags .tag { - margin-bottom: 0.5rem; } - .tags .tag:not(:last-child) { - margin-right: 0.5rem; } - .tags:last-child { - margin-bottom: -0.5rem; } - .tags:not(:last-child) { - margin-bottom: 1rem; } - .tags.has-addons .tag { - margin-right: 0; } - .tags.has-addons .tag:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; } - .tags.has-addons .tag:not(:last-child) { - border-bottom-right-radius: 0; - border-top-right-radius: 0; } - .tags.is-centered { - justify-content: center; } - .tags.is-centered .tag { - margin-right: 0.25rem; - margin-left: 0.25rem; } - .tags.is-right { - justify-content: flex-end; } - .tags.is-right .tag:not(:first-child) { - margin-left: 0.5rem; } - .tags.is-right .tag:not(:last-child) { - margin-right: 0; } - -.tag:not(body) { - align-items: center; - background-color: whitesmoke; - border-radius: 4px; - color: #4a4a4a; - display: inline-flex; - font-size: 0.75rem; - height: 2em; - justify-content: center; - line-height: 1.5; - padding-left: 0.75em; - padding-right: 0.75em; - white-space: nowrap; } - .tag:not(body) .delete { - margin-left: 0.25rem; - margin-right: -0.375rem; } - .tag:not(body).is-white { - background-color: white; - color: #0a0a0a; } - .tag:not(body).is-black { - background-color: #0a0a0a; - color: white; } - .tag:not(body).is-light { - background-color: whitesmoke; - color: #363636; } - .tag:not(body).is-dark { - background-color: #363636; - color: whitesmoke; } - .tag:not(body).is-primary { - background-color: #00d1b2; - color: #fff; } - .tag:not(body).is-link { - background-color: #33B2E8; - color: #fff; } - .tag:not(body).is-info { - background-color: #209cee; - color: #fff; } - .tag:not(body).is-success { - background-color: #23d160; - color: #fff; } - .tag:not(body).is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } - .tag:not(body).is-danger { - background-color: #ff3860; - color: #fff; } - .tag:not(body).is-medium { - font-size: 1rem; } - .tag:not(body).is-large { - font-size: 1.25rem; } - .tag:not(body) .icon:first-child:not(:last-child) { - margin-left: -0.375em; - margin-right: 0.1875em; } - .tag:not(body) .icon:last-child:not(:first-child) { - margin-left: 0.1875em; - margin-right: -0.375em; } - .tag:not(body) .icon:first-child:last-child { - margin-left: -0.375em; - margin-right: -0.375em; } - .tag:not(body).is-delete { - margin-left: 1px; - padding: 0; - position: relative; - width: 2em; } - .tag:not(body).is-delete::before, .tag:not(body).is-delete::after { - background-color: currentColor; - content: ""; - display: block; - left: 50%; - position: absolute; - top: 50%; - transform: translateX(-50%) translateY(-50%) rotate(45deg); - transform-origin: center center; } - .tag:not(body).is-delete::before { - height: 1px; - width: 50%; } - .tag:not(body).is-delete::after { - height: 50%; - width: 1px; } - .tag:not(body).is-delete:hover, .tag:not(body).is-delete:focus { - background-color: #e8e8e8; } - .tag:not(body).is-delete:active { - background-color: #dbdbdb; } - .tag:not(body).is-rounded { - border-radius: 290486px; } - -a.tag:hover { - text-decoration: underline; } - -.title, -.subtitle { - word-break: break-word; } - .title em, - .title span, - .subtitle em, - .subtitle span { - font-weight: inherit; } - .title sub, - .subtitle sub { - font-size: 0.75em; } - .title sup, - .subtitle sup { - font-size: 0.75em; } - .title .tag, - .subtitle .tag { - vertical-align: middle; } - -.title { - color: #363636; - font-size: 2rem; - font-weight: 600; - line-height: 1.125; } - .title strong { - color: inherit; - font-weight: inherit; } - .title + .highlight { - margin-top: -0.75rem; } - .title:not(.is-spaced) + .subtitle { - margin-top: -1.25rem; } - .title.is-1 { - font-size: 3rem; } - .title.is-2 { - font-size: 2.5rem; } - .title.is-3 { - font-size: 2rem; } - .title.is-4 { - font-size: 1.5rem; } - .title.is-5 { - font-size: 1.25rem; } - .title.is-6 { - font-size: 1rem; } - .title.is-7 { - font-size: 0.75rem; } - -.subtitle { - color: #4a4a4a; - font-size: 1.25rem; - font-weight: 400; - line-height: 1.25; } - .subtitle strong { - color: #363636; - font-weight: 600; } - .subtitle:not(.is-spaced) + .title { - margin-top: -1.25rem; } - .subtitle.is-1 { - font-size: 3rem; } - .subtitle.is-2 { - font-size: 2.5rem; } - .subtitle.is-3 { - font-size: 2rem; } - .subtitle.is-4 { - font-size: 1.5rem; } - .subtitle.is-5 { - font-size: 1.25rem; } - .subtitle.is-6 { - font-size: 1rem; } - .subtitle.is-7 { - font-size: 0.75rem; } - -.heading { - display: block; - font-size: 11px; - letter-spacing: 1px; - margin-bottom: 5px; - text-transform: uppercase; } - -.highlight { - font-weight: 400; - max-width: 100%; - overflow: hidden; - padding: 0; } - .highlight pre { - overflow: auto; - max-width: 100%; } - -.number { - align-items: center; - background-color: whitesmoke; - border-radius: 290486px; - display: inline-flex; - font-size: 1.25rem; - height: 2em; - justify-content: center; - margin-right: 1.5rem; - min-width: 2.5em; - padding: 0.25rem 0.5rem; - text-align: center; - vertical-align: top; } - -.breadcrumb { - font-size: 1rem; - white-space: nowrap; } - .breadcrumb a { - align-items: center; - color: #33B2E8; - display: flex; - justify-content: center; - padding: 0 0.75em; } - .breadcrumb a:hover { - color: #363636; } - .breadcrumb li { - align-items: center; - display: flex; } - .breadcrumb li:first-child a { - padding-left: 0; } - .breadcrumb li.is-active a { - color: #363636; - cursor: default; - pointer-events: none; } - .breadcrumb li + li::before { - color: #b5b5b5; - content: "\0002f"; } - .breadcrumb ul, - .breadcrumb ol { - align-items: flex-start; - display: flex; - flex-wrap: wrap; - justify-content: flex-start; } - .breadcrumb .icon:first-child { - margin-right: 0.5em; } - .breadcrumb .icon:last-child { - margin-left: 0.5em; } - .breadcrumb.is-centered ol, - .breadcrumb.is-centered ul { - justify-content: center; } - .breadcrumb.is-right ol, - .breadcrumb.is-right ul { - justify-content: flex-end; } - .breadcrumb.is-small { - font-size: 0.75rem; } - .breadcrumb.is-medium { - font-size: 1.25rem; } - .breadcrumb.is-large { - font-size: 1.5rem; } - .breadcrumb.has-arrow-separator li + li::before { - content: "\02192"; } - .breadcrumb.has-bullet-separator li + li::before { - content: "\02022"; } - .breadcrumb.has-dot-separator li + li::before { - content: "\000b7"; } - .breadcrumb.has-succeeds-separator li + li::before { - content: "\0227B"; } - -.card { - background-color: white; - box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); - color: #4a4a4a; - max-width: 100%; - position: relative; } - -.card-header { - background-color: none; - align-items: stretch; - box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1); - display: flex; } - -.card-header-title { - align-items: center; - color: #363636; - display: flex; - flex-grow: 1; - font-weight: 700; - padding: 0.75rem; } - .card-header-title.is-centered { - justify-content: center; } - -.card-header-icon { - align-items: center; - cursor: pointer; - display: flex; - justify-content: center; - padding: 0.75rem; } - -.card-image { - display: block; - position: relative; } - -.card-content { - background-color: none; - padding: 1.5rem; } - -.card-footer { - background-color: none; - border-top: 1px solid #dbdbdb; - align-items: stretch; - display: flex; } - -.card-footer-item { - align-items: center; - display: flex; - flex-basis: 0; - flex-grow: 1; - flex-shrink: 0; - justify-content: center; - padding: 0.75rem; } - .card-footer-item:not(:last-child) { - border-right: 1px solid #dbdbdb; } - -.card .media:not(:last-child) { - margin-bottom: 0.75rem; } - -.dropdown { - display: inline-flex; - position: relative; - vertical-align: top; } - .dropdown.is-active .dropdown-menu, .dropdown.is-hoverable:hover .dropdown-menu { - display: block; } - .dropdown.is-right .dropdown-menu { - left: auto; - right: 0; } - .dropdown.is-up .dropdown-menu { - bottom: 100%; - padding-bottom: 4px; - padding-top: initial; - top: auto; } - -.dropdown-menu { - display: none; - left: 0; - min-width: 12rem; - padding-top: 4px; - position: absolute; - top: 100%; - z-index: 20; } - -.dropdown-content { - background-color: white; - border-radius: 4px; - box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); - padding-bottom: 0.5rem; - padding-top: 0.5rem; } - -.dropdown-item { - color: #4a4a4a; - display: block; - font-size: 0.875rem; - line-height: 1.5; - padding: 0.375rem 1rem; - position: relative; } - -a.dropdown-item { - padding-right: 3rem; - white-space: nowrap; } - a.dropdown-item:hover { - background-color: whitesmoke; - color: #0a0a0a; } - a.dropdown-item.is-active { - background-color: #33B2E8; - color: #fff; } - -.dropdown-divider { - background-color: #dbdbdb; - border: none; - display: block; - height: 1px; - margin: 0.5rem 0; } - -.level { - align-items: center; - justify-content: space-between; } - .level code { - border-radius: 4px; } - .level img { - display: inline-block; - vertical-align: top; } - .level.is-mobile { - display: flex; } - .level.is-mobile .level-left, - .level.is-mobile .level-right { - display: flex; } - .level.is-mobile .level-left + .level-right { - margin-top: 0; } - .level.is-mobile .level-item { - margin-right: 0.75rem; } - .level.is-mobile .level-item:not(:last-child) { - margin-bottom: 0; } - .level.is-mobile .level-item:not(.is-narrow) { - flex-grow: 1; } - @media screen and (min-width: 769px), print { - .level { - display: flex; } - .level > .level-item:not(.is-narrow) { - flex-grow: 1; } } - -.level-item { - align-items: center; - display: flex; - flex-basis: auto; - flex-grow: 0; - flex-shrink: 0; - justify-content: center; } - .level-item .title, - .level-item .subtitle { - margin-bottom: 0; } - @media screen and (max-width: 768px) { - .level-item:not(:last-child) { - margin-bottom: 0.75rem; } } - -.level-left, -.level-right { - flex-basis: auto; - flex-grow: 0; - flex-shrink: 0; } - .level-left .level-item.is-flexible, - .level-right .level-item.is-flexible { - flex-grow: 1; } - @media screen and (min-width: 769px), print { - .level-left .level-item:not(:last-child), - .level-right .level-item:not(:last-child) { - margin-right: 0.75rem; } } - -.level-left { - align-items: center; - justify-content: flex-start; } - @media screen and (max-width: 768px) { - .level-left + .level-right { - margin-top: 1.5rem; } } - @media screen and (min-width: 769px), print { - .level-left { - display: flex; } } - -.level-right { - align-items: center; - justify-content: flex-end; } - @media screen and (min-width: 769px), print { - .level-right { - display: flex; } } - -.media { - align-items: flex-start; - display: flex; - text-align: left; } - .media .content:not(:last-child) { - margin-bottom: 0.75rem; } - .media .media { - border-top: 1px solid rgba(219, 219, 219, 0.5); - display: flex; - padding-top: 0.75rem; } - .media .media .content:not(:last-child), - .media .media .control:not(:last-child) { - margin-bottom: 0.5rem; } - .media .media .media { - padding-top: 0.5rem; } - .media .media .media + .media { - margin-top: 0.5rem; } - .media + .media { - border-top: 1px solid rgba(219, 219, 219, 0.5); - margin-top: 1rem; - padding-top: 1rem; } - .media.is-large + .media { - margin-top: 1.5rem; - padding-top: 1.5rem; } - -.media-left, -.media-right { - flex-basis: auto; - flex-grow: 0; - flex-shrink: 0; } - -.media-left { - margin-right: 1rem; } - -.media-right { - margin-left: 1rem; } - -.media-content { - flex-basis: auto; - flex-grow: 1; - flex-shrink: 1; - text-align: left; } - -.menu { - font-size: 1rem; } - .menu.is-small { - font-size: 0.75rem; } - .menu.is-medium { - font-size: 1.25rem; } - .menu.is-large { - font-size: 1.5rem; } - -.menu-list { - line-height: 1.25; } - .menu-list a { - border-radius: 2px; - color: #4a4a4a; - display: block; - padding: 0.5em 0.75em; } - .menu-list a:hover { - background-color: whitesmoke; - color: #363636; } - .menu-list a.is-active { - background-color: #33B2E8; - color: #fff; } - .menu-list li ul { - border-left: 1px solid #dbdbdb; - margin: 0.75em; - padding-left: 0.75em; } - -.menu-label { - color: #7a7a7a; - font-size: 0.75em; - letter-spacing: 0.1em; - text-transform: uppercase; } - .menu-label:not(:first-child) { - margin-top: 1em; } - .menu-label:not(:last-child) { - margin-bottom: 1em; } - -.message { - background-color: whitesmoke; - border-radius: 4px; - font-size: 1rem; } - .message strong { - color: currentColor; } - .message a:not(.button):not(.tag) { - color: currentColor; - text-decoration: underline; } - .message.is-small { - font-size: 0.75rem; } - .message.is-medium { - font-size: 1.25rem; } - .message.is-large { - font-size: 1.5rem; } - .message.is-white { - background-color: white; } - .message.is-white .message-header { - background-color: white; - color: #0a0a0a; } - .message.is-white .message-body { - border-color: white; - color: #4d4d4d; } - .message.is-black { - background-color: #fafafa; } - .message.is-black .message-header { - background-color: #0a0a0a; - color: white; } - .message.is-black .message-body { - border-color: #0a0a0a; - color: #090909; } - .message.is-light { - background-color: #fafafa; } - .message.is-light .message-header { - background-color: whitesmoke; - color: #363636; } - .message.is-light .message-body { - border-color: whitesmoke; - color: #505050; } - .message.is-dark { - background-color: #fafafa; } - .message.is-dark .message-header { - background-color: #363636; - color: whitesmoke; } - .message.is-dark .message-body { - border-color: #363636; - color: #2a2a2a; } - .message.is-primary { - background-color: #f5fffd; } - .message.is-primary .message-header { - background-color: #00d1b2; - color: #fff; } - .message.is-primary .message-body { - border-color: #00d1b2; - color: #021310; } - .message.is-link { - background-color: #f6fcfe; } - .message.is-link .message-header { - background-color: #33B2E8; - color: #fff; } - .message.is-link .message-body { - border-color: #33B2E8; - color: #15516a; } - .message.is-info { - background-color: #f6fbfe; } - .message.is-info .message-header { - background-color: #209cee; - color: #fff; } - .message.is-info .message-body { - border-color: #209cee; - color: #12537e; } - .message.is-success { - background-color: #f6fef9; } - .message.is-success .message-header { - background-color: #23d160; - color: #fff; } - .message.is-success .message-body { - border-color: #23d160; - color: #0e301a; } - .message.is-warning { - background-color: #fffdf5; } - .message.is-warning .message-header { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } - .message.is-warning .message-body { - border-color: #ffdd57; - color: #3b3108; } - .message.is-danger { - background-color: #fff5f7; } - .message.is-danger .message-header { - background-color: #ff3860; - color: #fff; } - .message.is-danger .message-body { - border-color: #ff3860; - color: #cd0930; } - -.message-header { - align-items: center; - background-color: #4a4a4a; - border-radius: 4px 4px 0 0; - color: #fff; - display: flex; - font-weight: 700; - justify-content: space-between; - line-height: 1.25; - padding: 0.75em 1em; - position: relative; } - .message-header .delete { - flex-grow: 0; - flex-shrink: 0; - margin-left: 0.75em; } - .message-header + .message-body { - border-width: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; } - -.message-body { - border-color: #dbdbdb; - border-radius: 4px; - border-style: solid; - border-width: 0 0 0 4px; - color: #4a4a4a; - padding: 1.25em 1.5em; } - .message-body code, - .message-body pre { - background-color: white; } - .message-body pre code { - background-color: transparent; } - -.modal { - align-items: center; - display: none; - justify-content: center; - overflow: hidden; - position: fixed; - z-index: 40; } - .modal.is-active { - display: flex; } - -.modal-background { - background-color: rgba(10, 10, 10, 0.86); } - -.modal-content, -.modal-card { - margin: 0 20px; - max-height: calc(100vh - 160px); - overflow: auto; - position: relative; - width: 100%; } - @media screen and (min-width: 769px), print { - .modal-content, - .modal-card { - margin: 0 auto; - max-height: calc(100vh - 40px); - width: 640px; } } - -.modal-close { - background: none; - height: 40px; - position: fixed; - right: 20px; - top: 20px; - width: 40px; } - -.modal-card { - display: flex; - flex-direction: column; - max-height: calc(100vh - 40px); - overflow: hidden; } - -.modal-card-head, -.modal-card-foot { - align-items: center; - background-color: whitesmoke; - display: flex; - flex-shrink: 0; - justify-content: flex-start; - padding: 20px; - position: relative; } - -.modal-card-head { - border-bottom: 1px solid #dbdbdb; - border-top-left-radius: 6px; - border-top-right-radius: 6px; } - -.modal-card-title { - color: #363636; - flex-grow: 1; - flex-shrink: 0; - font-size: 1.5rem; - line-height: 1; } - -.modal-card-foot { - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - border-top: 1px solid #dbdbdb; } - .modal-card-foot .button:not(:last-child) { - margin-right: 10px; } - -.modal-card-body { - -webkit-overflow-scrolling: touch; - background-color: white; - flex-grow: 1; - flex-shrink: 1; - overflow: auto; - padding: 20px; } - -.navbar { - background-color: white; - min-height: 3.25rem; - position: relative; - z-index: 30; } - .navbar.is-white { - background-color: white; - color: #0a0a0a; } - .navbar.is-white .navbar-brand > .navbar-item, - .navbar.is-white .navbar-brand .navbar-link { - color: #0a0a0a; } - .navbar.is-white .navbar-brand > a.navbar-item:hover, .navbar.is-white .navbar-brand > a.navbar-item.is-active, - .navbar.is-white .navbar-brand .navbar-link:hover, - .navbar.is-white .navbar-brand .navbar-link.is-active { - background-color: #f2f2f2; - color: #0a0a0a; } - .navbar.is-white .navbar-brand .navbar-link::after { - border-color: #0a0a0a; } - @media screen and (min-width: 1088px) { - .navbar.is-white .navbar-start > .navbar-item, - .navbar.is-white .navbar-start .navbar-link, - .navbar.is-white .navbar-end > .navbar-item, - .navbar.is-white .navbar-end .navbar-link { - color: #0a0a0a; } - .navbar.is-white .navbar-start > a.navbar-item:hover, .navbar.is-white .navbar-start > a.navbar-item.is-active, - .navbar.is-white .navbar-start .navbar-link:hover, - .navbar.is-white .navbar-start .navbar-link.is-active, - .navbar.is-white .navbar-end > a.navbar-item:hover, - .navbar.is-white .navbar-end > a.navbar-item.is-active, - .navbar.is-white .navbar-end .navbar-link:hover, - .navbar.is-white .navbar-end .navbar-link.is-active { - background-color: #f2f2f2; - color: #0a0a0a; } - .navbar.is-white .navbar-start .navbar-link::after, - .navbar.is-white .navbar-end .navbar-link::after { - border-color: #0a0a0a; } - .navbar.is-white .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-white .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #f2f2f2; - color: #0a0a0a; } - .navbar.is-white .navbar-dropdown a.navbar-item.is-active { - background-color: white; - color: #0a0a0a; } } - .navbar.is-black { - background-color: #0a0a0a; - color: white; } - .navbar.is-black .navbar-brand > .navbar-item, - .navbar.is-black .navbar-brand .navbar-link { - color: white; } - .navbar.is-black .navbar-brand > a.navbar-item:hover, .navbar.is-black .navbar-brand > a.navbar-item.is-active, - .navbar.is-black .navbar-brand .navbar-link:hover, - .navbar.is-black .navbar-brand .navbar-link.is-active { - background-color: black; - color: white; } - .navbar.is-black .navbar-brand .navbar-link::after { - border-color: white; } - @media screen and (min-width: 1088px) { - .navbar.is-black .navbar-start > .navbar-item, - .navbar.is-black .navbar-start .navbar-link, - .navbar.is-black .navbar-end > .navbar-item, - .navbar.is-black .navbar-end .navbar-link { - color: white; } - .navbar.is-black .navbar-start > a.navbar-item:hover, .navbar.is-black .navbar-start > a.navbar-item.is-active, - .navbar.is-black .navbar-start .navbar-link:hover, - .navbar.is-black .navbar-start .navbar-link.is-active, - .navbar.is-black .navbar-end > a.navbar-item:hover, - .navbar.is-black .navbar-end > a.navbar-item.is-active, - .navbar.is-black .navbar-end .navbar-link:hover, - .navbar.is-black .navbar-end .navbar-link.is-active { - background-color: black; - color: white; } - .navbar.is-black .navbar-start .navbar-link::after, - .navbar.is-black .navbar-end .navbar-link::after { - border-color: white; } - .navbar.is-black .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-black .navbar-item.has-dropdown.is-active .navbar-link { - background-color: black; - color: white; } - .navbar.is-black .navbar-dropdown a.navbar-item.is-active { - background-color: #0a0a0a; - color: white; } } - .navbar.is-light { - background-color: whitesmoke; - color: #363636; } - .navbar.is-light .navbar-brand > .navbar-item, - .navbar.is-light .navbar-brand .navbar-link { - color: #363636; } - .navbar.is-light .navbar-brand > a.navbar-item:hover, .navbar.is-light .navbar-brand > a.navbar-item.is-active, - .navbar.is-light .navbar-brand .navbar-link:hover, - .navbar.is-light .navbar-brand .navbar-link.is-active { - background-color: #e8e8e8; - color: #363636; } - .navbar.is-light .navbar-brand .navbar-link::after { - border-color: #363636; } - @media screen and (min-width: 1088px) { - .navbar.is-light .navbar-start > .navbar-item, - .navbar.is-light .navbar-start .navbar-link, - .navbar.is-light .navbar-end > .navbar-item, - .navbar.is-light .navbar-end .navbar-link { - color: #363636; } - .navbar.is-light .navbar-start > a.navbar-item:hover, .navbar.is-light .navbar-start > a.navbar-item.is-active, - .navbar.is-light .navbar-start .navbar-link:hover, - .navbar.is-light .navbar-start .navbar-link.is-active, - .navbar.is-light .navbar-end > a.navbar-item:hover, - .navbar.is-light .navbar-end > a.navbar-item.is-active, - .navbar.is-light .navbar-end .navbar-link:hover, - .navbar.is-light .navbar-end .navbar-link.is-active { - background-color: #e8e8e8; - color: #363636; } - .navbar.is-light .navbar-start .navbar-link::after, - .navbar.is-light .navbar-end .navbar-link::after { - border-color: #363636; } - .navbar.is-light .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-light .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #e8e8e8; - color: #363636; } - .navbar.is-light .navbar-dropdown a.navbar-item.is-active { - background-color: whitesmoke; - color: #363636; } } - .navbar.is-dark { - background-color: #363636; - color: whitesmoke; } - .navbar.is-dark .navbar-brand > .navbar-item, - .navbar.is-dark .navbar-brand .navbar-link { - color: whitesmoke; } - .navbar.is-dark .navbar-brand > a.navbar-item:hover, .navbar.is-dark .navbar-brand > a.navbar-item.is-active, - .navbar.is-dark .navbar-brand .navbar-link:hover, - .navbar.is-dark .navbar-brand .navbar-link.is-active { - background-color: #292929; - color: whitesmoke; } - .navbar.is-dark .navbar-brand .navbar-link::after { - border-color: whitesmoke; } - @media screen and (min-width: 1088px) { - .navbar.is-dark .navbar-start > .navbar-item, - .navbar.is-dark .navbar-start .navbar-link, - .navbar.is-dark .navbar-end > .navbar-item, - .navbar.is-dark .navbar-end .navbar-link { - color: whitesmoke; } - .navbar.is-dark .navbar-start > a.navbar-item:hover, .navbar.is-dark .navbar-start > a.navbar-item.is-active, - .navbar.is-dark .navbar-start .navbar-link:hover, - .navbar.is-dark .navbar-start .navbar-link.is-active, - .navbar.is-dark .navbar-end > a.navbar-item:hover, - .navbar.is-dark .navbar-end > a.navbar-item.is-active, - .navbar.is-dark .navbar-end .navbar-link:hover, - .navbar.is-dark .navbar-end .navbar-link.is-active { - background-color: #292929; - color: whitesmoke; } - .navbar.is-dark .navbar-start .navbar-link::after, - .navbar.is-dark .navbar-end .navbar-link::after { - border-color: whitesmoke; } - .navbar.is-dark .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-dark .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #292929; - color: whitesmoke; } - .navbar.is-dark .navbar-dropdown a.navbar-item.is-active { - background-color: #363636; - color: whitesmoke; } } - .navbar.is-primary { - background-color: #00d1b2; - color: #fff; } - .navbar.is-primary .navbar-brand > .navbar-item, - .navbar.is-primary .navbar-brand .navbar-link { - color: #fff; } - .navbar.is-primary .navbar-brand > a.navbar-item:hover, .navbar.is-primary .navbar-brand > a.navbar-item.is-active, - .navbar.is-primary .navbar-brand .navbar-link:hover, - .navbar.is-primary .navbar-brand .navbar-link.is-active { - background-color: #00b89c; - color: #fff; } - .navbar.is-primary .navbar-brand .navbar-link::after { - border-color: #fff; } - @media screen and (min-width: 1088px) { - .navbar.is-primary .navbar-start > .navbar-item, - .navbar.is-primary .navbar-start .navbar-link, - .navbar.is-primary .navbar-end > .navbar-item, - .navbar.is-primary .navbar-end .navbar-link { - color: #fff; } - .navbar.is-primary .navbar-start > a.navbar-item:hover, .navbar.is-primary .navbar-start > a.navbar-item.is-active, - .navbar.is-primary .navbar-start .navbar-link:hover, - .navbar.is-primary .navbar-start .navbar-link.is-active, - .navbar.is-primary .navbar-end > a.navbar-item:hover, - .navbar.is-primary .navbar-end > a.navbar-item.is-active, - .navbar.is-primary .navbar-end .navbar-link:hover, - .navbar.is-primary .navbar-end .navbar-link.is-active { - background-color: #00b89c; - color: #fff; } - .navbar.is-primary .navbar-start .navbar-link::after, - .navbar.is-primary .navbar-end .navbar-link::after { - border-color: #fff; } - .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #00b89c; - color: #fff; } - .navbar.is-primary .navbar-dropdown a.navbar-item.is-active { - background-color: #00d1b2; - color: #fff; } } - .navbar.is-link { - background-color: #33B2E8; - color: #fff; } - .navbar.is-link .navbar-brand > .navbar-item, - .navbar.is-link .navbar-brand .navbar-link { - color: #fff; } - .navbar.is-link .navbar-brand > a.navbar-item:hover, .navbar.is-link .navbar-brand > a.navbar-item.is-active, - .navbar.is-link .navbar-brand .navbar-link:hover, - .navbar.is-link .navbar-brand .navbar-link.is-active { - background-color: #1ca9e5; - color: #fff; } - .navbar.is-link .navbar-brand .navbar-link::after { - border-color: #fff; } - @media screen and (min-width: 1088px) { - .navbar.is-link .navbar-start > .navbar-item, - .navbar.is-link .navbar-start .navbar-link, - .navbar.is-link .navbar-end > .navbar-item, - .navbar.is-link .navbar-end .navbar-link { - color: #fff; } - .navbar.is-link .navbar-start > a.navbar-item:hover, .navbar.is-link .navbar-start > a.navbar-item.is-active, - .navbar.is-link .navbar-start .navbar-link:hover, - .navbar.is-link .navbar-start .navbar-link.is-active, - .navbar.is-link .navbar-end > a.navbar-item:hover, - .navbar.is-link .navbar-end > a.navbar-item.is-active, - .navbar.is-link .navbar-end .navbar-link:hover, - .navbar.is-link .navbar-end .navbar-link.is-active { - background-color: #1ca9e5; - color: #fff; } - .navbar.is-link .navbar-start .navbar-link::after, - .navbar.is-link .navbar-end .navbar-link::after { - border-color: #fff; } - .navbar.is-link .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-link .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #1ca9e5; - color: #fff; } - .navbar.is-link .navbar-dropdown a.navbar-item.is-active { - background-color: #33B2E8; - color: #fff; } } - .navbar.is-info { - background-color: #209cee; - color: #fff; } - .navbar.is-info .navbar-brand > .navbar-item, - .navbar.is-info .navbar-brand .navbar-link { - color: #fff; } - .navbar.is-info .navbar-brand > a.navbar-item:hover, .navbar.is-info .navbar-brand > a.navbar-item.is-active, - .navbar.is-info .navbar-brand .navbar-link:hover, - .navbar.is-info .navbar-brand .navbar-link.is-active { - background-color: #118fe4; - color: #fff; } - .navbar.is-info .navbar-brand .navbar-link::after { - border-color: #fff; } - @media screen and (min-width: 1088px) { - .navbar.is-info .navbar-start > .navbar-item, - .navbar.is-info .navbar-start .navbar-link, - .navbar.is-info .navbar-end > .navbar-item, - .navbar.is-info .navbar-end .navbar-link { - color: #fff; } - .navbar.is-info .navbar-start > a.navbar-item:hover, .navbar.is-info .navbar-start > a.navbar-item.is-active, - .navbar.is-info .navbar-start .navbar-link:hover, - .navbar.is-info .navbar-start .navbar-link.is-active, - .navbar.is-info .navbar-end > a.navbar-item:hover, - .navbar.is-info .navbar-end > a.navbar-item.is-active, - .navbar.is-info .navbar-end .navbar-link:hover, - .navbar.is-info .navbar-end .navbar-link.is-active { - background-color: #118fe4; - color: #fff; } - .navbar.is-info .navbar-start .navbar-link::after, - .navbar.is-info .navbar-end .navbar-link::after { - border-color: #fff; } - .navbar.is-info .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-info .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #118fe4; - color: #fff; } - .navbar.is-info .navbar-dropdown a.navbar-item.is-active { - background-color: #209cee; - color: #fff; } } - .navbar.is-success { - background-color: #23d160; - color: #fff; } - .navbar.is-success .navbar-brand > .navbar-item, - .navbar.is-success .navbar-brand .navbar-link { - color: #fff; } - .navbar.is-success .navbar-brand > a.navbar-item:hover, .navbar.is-success .navbar-brand > a.navbar-item.is-active, - .navbar.is-success .navbar-brand .navbar-link:hover, - .navbar.is-success .navbar-brand .navbar-link.is-active { - background-color: #20bc56; - color: #fff; } - .navbar.is-success .navbar-brand .navbar-link::after { - border-color: #fff; } - @media screen and (min-width: 1088px) { - .navbar.is-success .navbar-start > .navbar-item, - .navbar.is-success .navbar-start .navbar-link, - .navbar.is-success .navbar-end > .navbar-item, - .navbar.is-success .navbar-end .navbar-link { - color: #fff; } - .navbar.is-success .navbar-start > a.navbar-item:hover, .navbar.is-success .navbar-start > a.navbar-item.is-active, - .navbar.is-success .navbar-start .navbar-link:hover, - .navbar.is-success .navbar-start .navbar-link.is-active, - .navbar.is-success .navbar-end > a.navbar-item:hover, - .navbar.is-success .navbar-end > a.navbar-item.is-active, - .navbar.is-success .navbar-end .navbar-link:hover, - .navbar.is-success .navbar-end .navbar-link.is-active { - background-color: #20bc56; - color: #fff; } - .navbar.is-success .navbar-start .navbar-link::after, - .navbar.is-success .navbar-end .navbar-link::after { - border-color: #fff; } - .navbar.is-success .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-success .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #20bc56; - color: #fff; } - .navbar.is-success .navbar-dropdown a.navbar-item.is-active { - background-color: #23d160; - color: #fff; } } - .navbar.is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } - .navbar.is-warning .navbar-brand > .navbar-item, - .navbar.is-warning .navbar-brand .navbar-link { - color: rgba(0, 0, 0, 0.7); } - .navbar.is-warning .navbar-brand > a.navbar-item:hover, .navbar.is-warning .navbar-brand > a.navbar-item.is-active, - .navbar.is-warning .navbar-brand .navbar-link:hover, - .navbar.is-warning .navbar-brand .navbar-link.is-active { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); } - .navbar.is-warning .navbar-brand .navbar-link::after { - border-color: rgba(0, 0, 0, 0.7); } - @media screen and (min-width: 1088px) { - .navbar.is-warning .navbar-start > .navbar-item, - .navbar.is-warning .navbar-start .navbar-link, - .navbar.is-warning .navbar-end > .navbar-item, - .navbar.is-warning .navbar-end .navbar-link { - color: rgba(0, 0, 0, 0.7); } - .navbar.is-warning .navbar-start > a.navbar-item:hover, .navbar.is-warning .navbar-start > a.navbar-item.is-active, - .navbar.is-warning .navbar-start .navbar-link:hover, - .navbar.is-warning .navbar-start .navbar-link.is-active, - .navbar.is-warning .navbar-end > a.navbar-item:hover, - .navbar.is-warning .navbar-end > a.navbar-item.is-active, - .navbar.is-warning .navbar-end .navbar-link:hover, - .navbar.is-warning .navbar-end .navbar-link.is-active { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); } - .navbar.is-warning .navbar-start .navbar-link::after, - .navbar.is-warning .navbar-end .navbar-link::after { - border-color: rgba(0, 0, 0, 0.7); } - .navbar.is-warning .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-warning .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); } - .navbar.is-warning .navbar-dropdown a.navbar-item.is-active { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } } - .navbar.is-danger { - background-color: #ff3860; - color: #fff; } - .navbar.is-danger .navbar-brand > .navbar-item, - .navbar.is-danger .navbar-brand .navbar-link { - color: #fff; } - .navbar.is-danger .navbar-brand > a.navbar-item:hover, .navbar.is-danger .navbar-brand > a.navbar-item.is-active, - .navbar.is-danger .navbar-brand .navbar-link:hover, - .navbar.is-danger .navbar-brand .navbar-link.is-active { - background-color: #ff1f4b; - color: #fff; } - .navbar.is-danger .navbar-brand .navbar-link::after { - border-color: #fff; } - @media screen and (min-width: 1088px) { - .navbar.is-danger .navbar-start > .navbar-item, - .navbar.is-danger .navbar-start .navbar-link, - .navbar.is-danger .navbar-end > .navbar-item, - .navbar.is-danger .navbar-end .navbar-link { - color: #fff; } - .navbar.is-danger .navbar-start > a.navbar-item:hover, .navbar.is-danger .navbar-start > a.navbar-item.is-active, - .navbar.is-danger .navbar-start .navbar-link:hover, - .navbar.is-danger .navbar-start .navbar-link.is-active, - .navbar.is-danger .navbar-end > a.navbar-item:hover, - .navbar.is-danger .navbar-end > a.navbar-item.is-active, - .navbar.is-danger .navbar-end .navbar-link:hover, - .navbar.is-danger .navbar-end .navbar-link.is-active { - background-color: #ff1f4b; - color: #fff; } - .navbar.is-danger .navbar-start .navbar-link::after, - .navbar.is-danger .navbar-end .navbar-link::after { - border-color: #fff; } - .navbar.is-danger .navbar-item.has-dropdown:hover .navbar-link, - .navbar.is-danger .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #ff1f4b; - color: #fff; } - .navbar.is-danger .navbar-dropdown a.navbar-item.is-active { - background-color: #ff3860; - color: #fff; } } - .navbar > .container { - align-items: stretch; - display: flex; - min-height: 3.25rem; - width: 100%; } - .navbar.has-shadow { - box-shadow: 0 2px 0 0 whitesmoke; } - .navbar.is-fixed-bottom, .navbar.is-fixed-top { - left: 0; - position: fixed; - right: 0; - z-index: 30; } - .navbar.is-fixed-bottom { - bottom: 0; } - .navbar.is-fixed-bottom.has-shadow { - box-shadow: 0 -2px 0 0 whitesmoke; } - .navbar.is-fixed-top { - top: 0; } - -html.has-navbar-fixed-top, -body.has-navbar-fixed-top { - padding-top: 3.25rem; } - -html.has-navbar-fixed-bottom, -body.has-navbar-fixed-bottom { - padding-bottom: 3.25rem; } - -.navbar-brand, -.navbar-tabs { - align-items: stretch; - display: flex; - flex-shrink: 0; - min-height: 3.25rem; } - -.navbar-brand a.navbar-item:hover { - background-color: transparent; } - -.navbar-tabs { - -webkit-overflow-scrolling: touch; - max-width: 100vw; - overflow-x: auto; - overflow-y: hidden; } - -.navbar-burger { - cursor: pointer; - display: block; - height: 3.25rem; - position: relative; - width: 3.25rem; - margin-left: auto; } - .navbar-burger span { - background-color: currentColor; - display: block; - height: 1px; - left: calc(50% - 8px); - position: absolute; - transform-origin: center; - transition-duration: 86ms; - transition-property: background-color, opacity, transform; - transition-timing-function: ease-out; - width: 16px; } - .navbar-burger span:nth-child(1) { - top: calc(50% - 6px); } - .navbar-burger span:nth-child(2) { - top: calc(50% - 1px); } - .navbar-burger span:nth-child(3) { - top: calc(50% + 4px); } - .navbar-burger:hover { - background-color: rgba(0, 0, 0, 0.05); } - .navbar-burger.is-active span:nth-child(1) { - transform: translateY(5px) rotate(45deg); } - .navbar-burger.is-active span:nth-child(2) { - opacity: 0; } - .navbar-burger.is-active span:nth-child(3) { - transform: translateY(-5px) rotate(-45deg); } - -.navbar-menu { - display: none; } - -.navbar-item, -.navbar-link { - color: #4a4a4a; - display: block; - line-height: 1.5; - padding: 0.5rem 0.75rem; - position: relative; } - .navbar-item .icon:only-child, - .navbar-link .icon:only-child { - margin-left: -0.25rem; - margin-right: -0.25rem; } - -a.navbar-item, -.navbar-link { - cursor: pointer; } - a.navbar-item:hover, a.navbar-item.is-active, - .navbar-link:hover, - .navbar-link.is-active { - background-color: #fafafa; - color: #33B2E8; } - -.navbar-item { - display: block; - flex-grow: 0; - flex-shrink: 0; } - .navbar-item img { - max-height: 1.75rem; } - .navbar-item.has-dropdown { - padding: 0; } - .navbar-item.is-expanded { - flex-grow: 1; - flex-shrink: 1; } - .navbar-item.is-tab { - border-bottom: 1px solid transparent; - min-height: 3.25rem; - padding-bottom: calc(0.5rem - 1px); } - .navbar-item.is-tab:hover { - background-color: transparent; - border-bottom-color: #33B2E8; } - .navbar-item.is-tab.is-active { - background-color: transparent; - border-bottom-color: #33B2E8; - border-bottom-style: solid; - border-bottom-width: 3px; - color: #33B2E8; - padding-bottom: calc(0.5rem - 3px); } - -.navbar-content { - flex-grow: 1; - flex-shrink: 1; } - -.navbar-link { - padding-right: 2.5em; } - .navbar-link::after { - border-color: #33B2E8; - margin-top: -0.375em; - right: 1.125em; } - -.navbar-dropdown { - font-size: 0.875rem; - padding-bottom: 0.5rem; - padding-top: 0.5rem; } - .navbar-dropdown .navbar-item { - padding-left: 1.5rem; - padding-right: 1.5rem; } - -.navbar-divider { - background-color: whitesmoke; - border: none; - display: none; - height: 2px; - margin: 0.5rem 0; } - -@media screen and (max-width: 1087px) { - .navbar > .container { - display: block; } - .navbar-brand .navbar-item, - .navbar-tabs .navbar-item { - align-items: center; - display: flex; } - .navbar-link::after { - display: none; } - .navbar-menu { - background-color: white; - box-shadow: 0 8px 16px rgba(10, 10, 10, 0.1); - padding: 0.5rem 0; } - .navbar-menu.is-active { - display: block; } - .navbar.is-fixed-bottom-touch, .navbar.is-fixed-top-touch { - left: 0; - position: fixed; - right: 0; - z-index: 30; } - .navbar.is-fixed-bottom-touch { - bottom: 0; } - .navbar.is-fixed-bottom-touch.has-shadow { - box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); } - .navbar.is-fixed-top-touch { - top: 0; } - .navbar.is-fixed-top .navbar-menu, .navbar.is-fixed-top-touch .navbar-menu { - -webkit-overflow-scrolling: touch; - max-height: calc(100vh - 3.25rem); - overflow: auto; } - html.has-navbar-fixed-top-touch, - body.has-navbar-fixed-top-touch { - padding-top: 3.25rem; } - html.has-navbar-fixed-bottom-touch, - body.has-navbar-fixed-bottom-touch { - padding-bottom: 3.25rem; } } - -@media screen and (min-width: 1088px) { - .navbar, - .navbar-menu, - .navbar-start, - .navbar-end { - align-items: stretch; - display: flex; } - .navbar { - min-height: 3.25rem; } - .navbar.is-spaced { - padding: 1rem 2rem; } - .navbar.is-spaced .navbar-start, - .navbar.is-spaced .navbar-end { - align-items: center; } - .navbar.is-spaced a.navbar-item, - .navbar.is-spaced .navbar-link { - border-radius: 4px; } - .navbar.is-transparent a.navbar-item:hover, .navbar.is-transparent a.navbar-item.is-active, - .navbar.is-transparent .navbar-link:hover, - .navbar.is-transparent .navbar-link.is-active { - background-color: transparent !important; } - .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link, .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link { - background-color: transparent !important; } - .navbar.is-transparent .navbar-dropdown a.navbar-item:hover { - background-color: whitesmoke; - color: #0a0a0a; } - .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active { - background-color: whitesmoke; - color: #33B2E8; } - .navbar-burger { - display: none; } - .navbar-item, - .navbar-link { - align-items: center; - display: flex; } - .navbar-item { - display: flex; } - .navbar-item.has-dropdown { - align-items: stretch; } - .navbar-item.has-dropdown-up .navbar-link::after { - transform: rotate(135deg) translate(0.25em, -0.25em); } - .navbar-item.has-dropdown-up .navbar-dropdown { - border-bottom: 2px solid #dbdbdb; - border-radius: 6px 6px 0 0; - border-top: none; - bottom: 100%; - box-shadow: 0 -8px 8px rgba(10, 10, 10, 0.1); - top: auto; } - .navbar-item.is-active .navbar-dropdown, .navbar-item.is-hoverable:hover .navbar-dropdown { - display: block; } - .navbar.is-spaced .navbar-item.is-active .navbar-dropdown, .navbar-item.is-active .navbar-dropdown.is-boxed, .navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown, .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed { - opacity: 1; - pointer-events: auto; - transform: translateY(0); } - .navbar-menu { - flex-grow: 1; - flex-shrink: 0; } - .navbar-start { - justify-content: flex-start; - margin-right: auto; } - .navbar-end { - justify-content: flex-end; - margin-left: auto; } - .navbar-dropdown { - background-color: white; - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - border-top: 2px solid #dbdbdb; - box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1); - display: none; - font-size: 0.875rem; - left: 0; - min-width: 100%; - position: absolute; - top: 100%; - z-index: 20; } - .navbar-dropdown .navbar-item { - padding: 0.375rem 1rem; - white-space: nowrap; } - .navbar-dropdown a.navbar-item { - padding-right: 3rem; } - .navbar-dropdown a.navbar-item:hover { - background-color: whitesmoke; - color: #0a0a0a; } - .navbar-dropdown a.navbar-item.is-active { - background-color: whitesmoke; - color: #33B2E8; } - .navbar.is-spaced .navbar-dropdown, .navbar-dropdown.is-boxed { - border-radius: 6px; - border-top: none; - box-shadow: 0 8px 8px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); - display: block; - opacity: 0; - pointer-events: none; - top: calc(100% + (-4px)); - transform: translateY(-5px); - transition-duration: 86ms; - transition-property: opacity, transform; } - .navbar-dropdown.is-right { - left: auto; - right: 0; } - .navbar-divider { - display: block; } - .navbar > .container .navbar-brand, - .container > .navbar .navbar-brand { - margin-left: -1rem; } - .navbar > .container .navbar-menu, - .container > .navbar .navbar-menu { - margin-right: -1rem; } - .navbar.is-fixed-bottom-desktop, .navbar.is-fixed-top-desktop { - left: 0; - position: fixed; - right: 0; - z-index: 30; } - .navbar.is-fixed-bottom-desktop { - bottom: 0; } - .navbar.is-fixed-bottom-desktop.has-shadow { - box-shadow: 0 -2px 3px rgba(10, 10, 10, 0.1); } - .navbar.is-fixed-top-desktop { - top: 0; } - html.has-navbar-fixed-top-desktop, - body.has-navbar-fixed-top-desktop { - padding-top: 3.25rem; } - html.has-navbar-fixed-bottom-desktop, - body.has-navbar-fixed-bottom-desktop { - padding-bottom: 3.25rem; } - html.has-spaced-navbar-fixed-top, - body.has-spaced-navbar-fixed-top { - padding-top: 5.25rem; } - html.has-spaced-navbar-fixed-bottom, - body.has-spaced-navbar-fixed-bottom { - padding-bottom: 5.25rem; } - a.navbar-item.is-active, - .navbar-link.is-active { - color: #0a0a0a; } - a.navbar-item.is-active:not(:hover), - .navbar-link.is-active:not(:hover) { - background-color: transparent; } - .navbar-item.has-dropdown:hover .navbar-link, .navbar-item.has-dropdown.is-active .navbar-link { - background-color: #fafafa; } } - -.pagination { - font-size: 1rem; - margin: -0.25rem; } - .pagination.is-small { - font-size: 0.75rem; } - .pagination.is-medium { - font-size: 1.25rem; } - .pagination.is-large { - font-size: 1.5rem; } - .pagination.is-rounded .pagination-previous, - .pagination.is-rounded .pagination-next { - padding-left: 1em; - padding-right: 1em; - border-radius: 290486px; } - .pagination.is-rounded .pagination-link { - border-radius: 290486px; } - -.pagination, -.pagination-list { - align-items: center; - display: flex; - justify-content: center; - text-align: center; } - -.pagination-previous, -.pagination-next, -.pagination-link, -.pagination-ellipsis { - font-size: 1em; - padding-left: 0.5em; - padding-right: 0.5em; - justify-content: center; - margin: 0.25rem; - text-align: center; } - -.pagination-previous, -.pagination-next, -.pagination-link { - border-color: #dbdbdb; - color: #363636; - min-width: 2.25em; } - .pagination-previous:hover, - .pagination-next:hover, - .pagination-link:hover { - border-color: #b5b5b5; - color: #363636; } - .pagination-previous:focus, - .pagination-next:focus, - .pagination-link:focus { - border-color: #33B2E8; } - .pagination-previous:active, - .pagination-next:active, - .pagination-link:active { - box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2); } - .pagination-previous[disabled], - .pagination-next[disabled], - .pagination-link[disabled] { - background-color: #dbdbdb; - border-color: #dbdbdb; - box-shadow: none; - color: #7a7a7a; - opacity: 0.5; } - -.pagination-previous, -.pagination-next { - padding-left: 0.75em; - padding-right: 0.75em; - white-space: nowrap; } - -.pagination-link.is-current { - background-color: #33B2E8; - border-color: #33B2E8; - color: #fff; } - -.pagination-ellipsis { - color: #b5b5b5; - pointer-events: none; } - -.pagination-list { - flex-wrap: wrap; } - -@media screen and (max-width: 768px) { - .pagination { - flex-wrap: wrap; } - .pagination-previous, - .pagination-next { - flex-grow: 1; - flex-shrink: 1; } - .pagination-list li { - flex-grow: 1; - flex-shrink: 1; } } - -@media screen and (min-width: 769px), print { - .pagination-list { - flex-grow: 1; - flex-shrink: 1; - justify-content: flex-start; - order: 1; } - .pagination-previous { - order: 2; } - .pagination-next { - order: 3; } - .pagination { - justify-content: space-between; } - .pagination.is-centered .pagination-previous { - order: 1; } - .pagination.is-centered .pagination-list { - justify-content: center; - order: 2; } - .pagination.is-centered .pagination-next { - order: 3; } - .pagination.is-right .pagination-previous { - order: 1; } - .pagination.is-right .pagination-next { - order: 2; } - .pagination.is-right .pagination-list { - justify-content: flex-end; - order: 3; } } - -.panel { - font-size: 1rem; } - .panel:not(:last-child) { - margin-bottom: 1.5rem; } - -.panel-heading, -.panel-tabs, -.panel-block { - border-bottom: 1px solid #dbdbdb; - border-left: 1px solid #dbdbdb; - border-right: 1px solid #dbdbdb; } - .panel-heading:first-child, - .panel-tabs:first-child, - .panel-block:first-child { - border-top: 1px solid #dbdbdb; } - -.panel-heading { - background-color: whitesmoke; - border-radius: 4px 4px 0 0; - color: #363636; - font-size: 1.25em; - font-weight: 300; - line-height: 1.25; - padding: 0.5em 0.75em; } - -.panel-tabs { - align-items: flex-end; - display: flex; - font-size: 0.875em; - justify-content: center; } - .panel-tabs a { - border-bottom: 1px solid #dbdbdb; - margin-bottom: -1px; - padding: 0.5em; } - .panel-tabs a.is-active { - border-bottom-color: #4a4a4a; - color: #363636; } - -.panel-list a { - color: #4a4a4a; } - .panel-list a:hover { - color: #33B2E8; } - -.panel-block { - align-items: center; - color: #363636; - display: flex; - justify-content: flex-start; - padding: 0.5em 0.75em; } - .panel-block input[type="checkbox"] { - margin-right: 0.75em; } - .panel-block > .control { - flex-grow: 1; - flex-shrink: 1; - width: 100%; } - .panel-block.is-wrapped { - flex-wrap: wrap; } - .panel-block.is-active { - border-left-color: #33B2E8; - color: #363636; } - .panel-block.is-active .panel-icon { - color: #33B2E8; } - -a.panel-block, -label.panel-block { - cursor: pointer; } - a.panel-block:hover, - label.panel-block:hover { - background-color: whitesmoke; } - -.panel-icon { - display: inline-block; - font-size: 14px; - height: 1em; - line-height: 1em; - text-align: center; - vertical-align: top; - width: 1em; - color: #7a7a7a; - margin-right: 0.75em; } - .panel-icon .fa { - font-size: inherit; - line-height: inherit; } - -.tabs { - -webkit-overflow-scrolling: touch; - align-items: stretch; - display: flex; - font-size: 1rem; - justify-content: space-between; - overflow: hidden; - overflow-x: auto; - white-space: nowrap; } - .tabs a { - align-items: center; - border-bottom-color: #dbdbdb; - border-bottom-style: solid; - border-bottom-width: 1px; - color: #4a4a4a; - display: flex; - justify-content: center; - margin-bottom: -1px; - padding: 0.5em 1em; - vertical-align: top; } - .tabs a:hover { - border-bottom-color: #363636; - color: #363636; } - .tabs li { - display: block; } - .tabs li.is-active a { - border-bottom-color: #33B2E8; - color: #33B2E8; } - .tabs ul { - align-items: center; - border-bottom-color: #dbdbdb; - border-bottom-style: solid; - border-bottom-width: 1px; - display: flex; - flex-grow: 1; - flex-shrink: 0; - justify-content: flex-start; } - .tabs ul.is-left { - padding-right: 0.75em; } - .tabs ul.is-center { - flex: none; - justify-content: center; - padding-left: 0.75em; - padding-right: 0.75em; } - .tabs ul.is-right { - justify-content: flex-end; - padding-left: 0.75em; } - .tabs .icon:first-child { - margin-right: 0.5em; } - .tabs .icon:last-child { - margin-left: 0.5em; } - .tabs.is-centered ul { - justify-content: center; } - .tabs.is-right ul { - justify-content: flex-end; } - .tabs.is-boxed a { - border: 1px solid transparent; - border-radius: 4px 4px 0 0; } - .tabs.is-boxed a:hover { - background-color: whitesmoke; - border-bottom-color: #dbdbdb; } - .tabs.is-boxed li.is-active a { - background-color: white; - border-color: #dbdbdb; - border-bottom-color: transparent !important; } - .tabs.is-fullwidth li { - flex-grow: 1; - flex-shrink: 0; } - .tabs.is-toggle a { - border-color: #dbdbdb; - border-style: solid; - border-width: 1px; - margin-bottom: 0; - position: relative; } - .tabs.is-toggle a:hover { - background-color: whitesmoke; - border-color: #b5b5b5; - z-index: 2; } - .tabs.is-toggle li + li { - margin-left: -1px; } - .tabs.is-toggle li:first-child a { - border-radius: 4px 0 0 4px; } - .tabs.is-toggle li:last-child a { - border-radius: 0 4px 4px 0; } - .tabs.is-toggle li.is-active a { - background-color: #33B2E8; - border-color: #33B2E8; - color: #fff; - z-index: 1; } - .tabs.is-toggle ul { - border-bottom: none; } - .tabs.is-toggle.is-toggle-rounded li:first-child a { - border-bottom-left-radius: 290486px; - border-top-left-radius: 290486px; - padding-left: 1.25em; } - .tabs.is-toggle.is-toggle-rounded li:last-child a { - border-bottom-right-radius: 290486px; - border-top-right-radius: 290486px; - padding-right: 1.25em; } - .tabs.is-small { - font-size: 0.75rem; } - .tabs.is-medium { - font-size: 1.25rem; } - .tabs.is-large { - font-size: 1.5rem; } - -.column { - display: block; - flex-basis: 0; - flex-grow: 1; - flex-shrink: 1; - padding: 0.75rem; } - .columns.is-mobile > .column.is-narrow { - flex: none; } - .columns.is-mobile > .column.is-full { - flex: none; - width: 100%; } - .columns.is-mobile > .column.is-three-quarters { - flex: none; - width: 75%; } - .columns.is-mobile > .column.is-two-thirds { - flex: none; - width: 66.6666%; } - .columns.is-mobile > .column.is-half { - flex: none; - width: 50%; } - .columns.is-mobile > .column.is-one-third { - flex: none; - width: 33.3333%; } - .columns.is-mobile > .column.is-one-quarter { - flex: none; - width: 25%; } - .columns.is-mobile > .column.is-one-fifth { - flex: none; - width: 20%; } - .columns.is-mobile > .column.is-two-fifths { - flex: none; - width: 40%; } - .columns.is-mobile > .column.is-three-fifths { - flex: none; - width: 60%; } - .columns.is-mobile > .column.is-four-fifths { - flex: none; - width: 80%; } - .columns.is-mobile > .column.is-offset-three-quarters { - margin-left: 75%; } - .columns.is-mobile > .column.is-offset-two-thirds { - margin-left: 66.6666%; } - .columns.is-mobile > .column.is-offset-half { - margin-left: 50%; } - .columns.is-mobile > .column.is-offset-one-third { - margin-left: 33.3333%; } - .columns.is-mobile > .column.is-offset-one-quarter { - margin-left: 25%; } - .columns.is-mobile > .column.is-offset-one-fifth { - margin-left: 20%; } - .columns.is-mobile > .column.is-offset-two-fifths { - margin-left: 40%; } - .columns.is-mobile > .column.is-offset-three-fifths { - margin-left: 60%; } - .columns.is-mobile > .column.is-offset-four-fifths { - margin-left: 80%; } - .columns.is-mobile > .column.is-1 { - flex: none; - width: 8.33333%; } - .columns.is-mobile > .column.is-offset-1 { - margin-left: 8.33333%; } - .columns.is-mobile > .column.is-2 { - flex: none; - width: 16.66667%; } - .columns.is-mobile > .column.is-offset-2 { - margin-left: 16.66667%; } - .columns.is-mobile > .column.is-3 { - flex: none; - width: 25%; } - .columns.is-mobile > .column.is-offset-3 { - margin-left: 25%; } - .columns.is-mobile > .column.is-4 { - flex: none; - width: 33.33333%; } - .columns.is-mobile > .column.is-offset-4 { - margin-left: 33.33333%; } - .columns.is-mobile > .column.is-5 { - flex: none; - width: 41.66667%; } - .columns.is-mobile > .column.is-offset-5 { - margin-left: 41.66667%; } - .columns.is-mobile > .column.is-6 { - flex: none; - width: 50%; } - .columns.is-mobile > .column.is-offset-6 { - margin-left: 50%; } - .columns.is-mobile > .column.is-7 { - flex: none; - width: 58.33333%; } - .columns.is-mobile > .column.is-offset-7 { - margin-left: 58.33333%; } - .columns.is-mobile > .column.is-8 { - flex: none; - width: 66.66667%; } - .columns.is-mobile > .column.is-offset-8 { - margin-left: 66.66667%; } - .columns.is-mobile > .column.is-9 { - flex: none; - width: 75%; } - .columns.is-mobile > .column.is-offset-9 { - margin-left: 75%; } - .columns.is-mobile > .column.is-10 { - flex: none; - width: 83.33333%; } - .columns.is-mobile > .column.is-offset-10 { - margin-left: 83.33333%; } - .columns.is-mobile > .column.is-11 { - flex: none; - width: 91.66667%; } - .columns.is-mobile > .column.is-offset-11 { - margin-left: 91.66667%; } - .columns.is-mobile > .column.is-12 { - flex: none; - width: 100%; } - .columns.is-mobile > .column.is-offset-12 { - margin-left: 100%; } - @media screen and (max-width: 768px) { - .column.is-narrow-mobile { - flex: none; } - .column.is-full-mobile { - flex: none; - width: 100%; } - .column.is-three-quarters-mobile { - flex: none; - width: 75%; } - .column.is-two-thirds-mobile { - flex: none; - width: 66.6666%; } - .column.is-half-mobile { - flex: none; - width: 50%; } - .column.is-one-third-mobile { - flex: none; - width: 33.3333%; } - .column.is-one-quarter-mobile { - flex: none; - width: 25%; } - .column.is-one-fifth-mobile { - flex: none; - width: 20%; } - .column.is-two-fifths-mobile { - flex: none; - width: 40%; } - .column.is-three-fifths-mobile { - flex: none; - width: 60%; } - .column.is-four-fifths-mobile { - flex: none; - width: 80%; } - .column.is-offset-three-quarters-mobile { - margin-left: 75%; } - .column.is-offset-two-thirds-mobile { - margin-left: 66.6666%; } - .column.is-offset-half-mobile { - margin-left: 50%; } - .column.is-offset-one-third-mobile { - margin-left: 33.3333%; } - .column.is-offset-one-quarter-mobile { - margin-left: 25%; } - .column.is-offset-one-fifth-mobile { - margin-left: 20%; } - .column.is-offset-two-fifths-mobile { - margin-left: 40%; } - .column.is-offset-three-fifths-mobile { - margin-left: 60%; } - .column.is-offset-four-fifths-mobile { - margin-left: 80%; } - .column.is-1-mobile { - flex: none; - width: 8.33333%; } - .column.is-offset-1-mobile { - margin-left: 8.33333%; } - .column.is-2-mobile { - flex: none; - width: 16.66667%; } - .column.is-offset-2-mobile { - margin-left: 16.66667%; } - .column.is-3-mobile { - flex: none; - width: 25%; } - .column.is-offset-3-mobile { - margin-left: 25%; } - .column.is-4-mobile { - flex: none; - width: 33.33333%; } - .column.is-offset-4-mobile { - margin-left: 33.33333%; } - .column.is-5-mobile { - flex: none; - width: 41.66667%; } - .column.is-offset-5-mobile { - margin-left: 41.66667%; } - .column.is-6-mobile { - flex: none; - width: 50%; } - .column.is-offset-6-mobile { - margin-left: 50%; } - .column.is-7-mobile { - flex: none; - width: 58.33333%; } - .column.is-offset-7-mobile { - margin-left: 58.33333%; } - .column.is-8-mobile { - flex: none; - width: 66.66667%; } - .column.is-offset-8-mobile { - margin-left: 66.66667%; } - .column.is-9-mobile { - flex: none; - width: 75%; } - .column.is-offset-9-mobile { - margin-left: 75%; } - .column.is-10-mobile { - flex: none; - width: 83.33333%; } - .column.is-offset-10-mobile { - margin-left: 83.33333%; } - .column.is-11-mobile { - flex: none; - width: 91.66667%; } - .column.is-offset-11-mobile { - margin-left: 91.66667%; } - .column.is-12-mobile { - flex: none; - width: 100%; } - .column.is-offset-12-mobile { - margin-left: 100%; } } - @media screen and (min-width: 769px), print { - .column.is-narrow, .column.is-narrow-tablet { - flex: none; } - .column.is-full, .column.is-full-tablet { - flex: none; - width: 100%; } - .column.is-three-quarters, .column.is-three-quarters-tablet { - flex: none; - width: 75%; } - .column.is-two-thirds, .column.is-two-thirds-tablet { - flex: none; - width: 66.6666%; } - .column.is-half, .column.is-half-tablet { - flex: none; - width: 50%; } - .column.is-one-third, .column.is-one-third-tablet { - flex: none; - width: 33.3333%; } - .column.is-one-quarter, .column.is-one-quarter-tablet { - flex: none; - width: 25%; } - .column.is-one-fifth, .column.is-one-fifth-tablet { - flex: none; - width: 20%; } - .column.is-two-fifths, .column.is-two-fifths-tablet { - flex: none; - width: 40%; } - .column.is-three-fifths, .column.is-three-fifths-tablet { - flex: none; - width: 60%; } - .column.is-four-fifths, .column.is-four-fifths-tablet { - flex: none; - width: 80%; } - .column.is-offset-three-quarters, .column.is-offset-three-quarters-tablet { - margin-left: 75%; } - .column.is-offset-two-thirds, .column.is-offset-two-thirds-tablet { - margin-left: 66.6666%; } - .column.is-offset-half, .column.is-offset-half-tablet { - margin-left: 50%; } - .column.is-offset-one-third, .column.is-offset-one-third-tablet { - margin-left: 33.3333%; } - .column.is-offset-one-quarter, .column.is-offset-one-quarter-tablet { - margin-left: 25%; } - .column.is-offset-one-fifth, .column.is-offset-one-fifth-tablet { - margin-left: 20%; } - .column.is-offset-two-fifths, .column.is-offset-two-fifths-tablet { - margin-left: 40%; } - .column.is-offset-three-fifths, .column.is-offset-three-fifths-tablet { - margin-left: 60%; } - .column.is-offset-four-fifths, .column.is-offset-four-fifths-tablet { - margin-left: 80%; } - .column.is-1, .column.is-1-tablet { - flex: none; - width: 8.33333%; } - .column.is-offset-1, .column.is-offset-1-tablet { - margin-left: 8.33333%; } - .column.is-2, .column.is-2-tablet { - flex: none; - width: 16.66667%; } - .column.is-offset-2, .column.is-offset-2-tablet { - margin-left: 16.66667%; } - .column.is-3, .column.is-3-tablet { - flex: none; - width: 25%; } - .column.is-offset-3, .column.is-offset-3-tablet { - margin-left: 25%; } - .column.is-4, .column.is-4-tablet { - flex: none; - width: 33.33333%; } - .column.is-offset-4, .column.is-offset-4-tablet { - margin-left: 33.33333%; } - .column.is-5, .column.is-5-tablet { - flex: none; - width: 41.66667%; } - .column.is-offset-5, .column.is-offset-5-tablet { - margin-left: 41.66667%; } - .column.is-6, .column.is-6-tablet { - flex: none; - width: 50%; } - .column.is-offset-6, .column.is-offset-6-tablet { - margin-left: 50%; } - .column.is-7, .column.is-7-tablet { - flex: none; - width: 58.33333%; } - .column.is-offset-7, .column.is-offset-7-tablet { - margin-left: 58.33333%; } - .column.is-8, .column.is-8-tablet { - flex: none; - width: 66.66667%; } - .column.is-offset-8, .column.is-offset-8-tablet { - margin-left: 66.66667%; } - .column.is-9, .column.is-9-tablet { - flex: none; - width: 75%; } - .column.is-offset-9, .column.is-offset-9-tablet { - margin-left: 75%; } - .column.is-10, .column.is-10-tablet { - flex: none; - width: 83.33333%; } - .column.is-offset-10, .column.is-offset-10-tablet { - margin-left: 83.33333%; } - .column.is-11, .column.is-11-tablet { - flex: none; - width: 91.66667%; } - .column.is-offset-11, .column.is-offset-11-tablet { - margin-left: 91.66667%; } - .column.is-12, .column.is-12-tablet { - flex: none; - width: 100%; } - .column.is-offset-12, .column.is-offset-12-tablet { - margin-left: 100%; } } - @media screen and (max-width: 1087px) { - .column.is-narrow-touch { - flex: none; } - .column.is-full-touch { - flex: none; - width: 100%; } - .column.is-three-quarters-touch { - flex: none; - width: 75%; } - .column.is-two-thirds-touch { - flex: none; - width: 66.6666%; } - .column.is-half-touch { - flex: none; - width: 50%; } - .column.is-one-third-touch { - flex: none; - width: 33.3333%; } - .column.is-one-quarter-touch { - flex: none; - width: 25%; } - .column.is-one-fifth-touch { - flex: none; - width: 20%; } - .column.is-two-fifths-touch { - flex: none; - width: 40%; } - .column.is-three-fifths-touch { - flex: none; - width: 60%; } - .column.is-four-fifths-touch { - flex: none; - width: 80%; } - .column.is-offset-three-quarters-touch { - margin-left: 75%; } - .column.is-offset-two-thirds-touch { - margin-left: 66.6666%; } - .column.is-offset-half-touch { - margin-left: 50%; } - .column.is-offset-one-third-touch { - margin-left: 33.3333%; } - .column.is-offset-one-quarter-touch { - margin-left: 25%; } - .column.is-offset-one-fifth-touch { - margin-left: 20%; } - .column.is-offset-two-fifths-touch { - margin-left: 40%; } - .column.is-offset-three-fifths-touch { - margin-left: 60%; } - .column.is-offset-four-fifths-touch { - margin-left: 80%; } - .column.is-1-touch { - flex: none; - width: 8.33333%; } - .column.is-offset-1-touch { - margin-left: 8.33333%; } - .column.is-2-touch { - flex: none; - width: 16.66667%; } - .column.is-offset-2-touch { - margin-left: 16.66667%; } - .column.is-3-touch { - flex: none; - width: 25%; } - .column.is-offset-3-touch { - margin-left: 25%; } - .column.is-4-touch { - flex: none; - width: 33.33333%; } - .column.is-offset-4-touch { - margin-left: 33.33333%; } - .column.is-5-touch { - flex: none; - width: 41.66667%; } - .column.is-offset-5-touch { - margin-left: 41.66667%; } - .column.is-6-touch { - flex: none; - width: 50%; } - .column.is-offset-6-touch { - margin-left: 50%; } - .column.is-7-touch { - flex: none; - width: 58.33333%; } - .column.is-offset-7-touch { - margin-left: 58.33333%; } - .column.is-8-touch { - flex: none; - width: 66.66667%; } - .column.is-offset-8-touch { - margin-left: 66.66667%; } - .column.is-9-touch { - flex: none; - width: 75%; } - .column.is-offset-9-touch { - margin-left: 75%; } - .column.is-10-touch { - flex: none; - width: 83.33333%; } - .column.is-offset-10-touch { - margin-left: 83.33333%; } - .column.is-11-touch { - flex: none; - width: 91.66667%; } - .column.is-offset-11-touch { - margin-left: 91.66667%; } - .column.is-12-touch { - flex: none; - width: 100%; } - .column.is-offset-12-touch { - margin-left: 100%; } } - @media screen and (min-width: 1088px) { - .column.is-narrow-desktop { - flex: none; } - .column.is-full-desktop { - flex: none; - width: 100%; } - .column.is-three-quarters-desktop { - flex: none; - width: 75%; } - .column.is-two-thirds-desktop { - flex: none; - width: 66.6666%; } - .column.is-half-desktop { - flex: none; - width: 50%; } - .column.is-one-third-desktop { - flex: none; - width: 33.3333%; } - .column.is-one-quarter-desktop { - flex: none; - width: 25%; } - .column.is-one-fifth-desktop { - flex: none; - width: 20%; } - .column.is-two-fifths-desktop { - flex: none; - width: 40%; } - .column.is-three-fifths-desktop { - flex: none; - width: 60%; } - .column.is-four-fifths-desktop { - flex: none; - width: 80%; } - .column.is-offset-three-quarters-desktop { - margin-left: 75%; } - .column.is-offset-two-thirds-desktop { - margin-left: 66.6666%; } - .column.is-offset-half-desktop { - margin-left: 50%; } - .column.is-offset-one-third-desktop { - margin-left: 33.3333%; } - .column.is-offset-one-quarter-desktop { - margin-left: 25%; } - .column.is-offset-one-fifth-desktop { - margin-left: 20%; } - .column.is-offset-two-fifths-desktop { - margin-left: 40%; } - .column.is-offset-three-fifths-desktop { - margin-left: 60%; } - .column.is-offset-four-fifths-desktop { - margin-left: 80%; } - .column.is-1-desktop { - flex: none; - width: 8.33333%; } - .column.is-offset-1-desktop { - margin-left: 8.33333%; } - .column.is-2-desktop { - flex: none; - width: 16.66667%; } - .column.is-offset-2-desktop { - margin-left: 16.66667%; } - .column.is-3-desktop { - flex: none; - width: 25%; } - .column.is-offset-3-desktop { - margin-left: 25%; } - .column.is-4-desktop { - flex: none; - width: 33.33333%; } - .column.is-offset-4-desktop { - margin-left: 33.33333%; } - .column.is-5-desktop { - flex: none; - width: 41.66667%; } - .column.is-offset-5-desktop { - margin-left: 41.66667%; } - .column.is-6-desktop { - flex: none; - width: 50%; } - .column.is-offset-6-desktop { - margin-left: 50%; } - .column.is-7-desktop { - flex: none; - width: 58.33333%; } - .column.is-offset-7-desktop { - margin-left: 58.33333%; } - .column.is-8-desktop { - flex: none; - width: 66.66667%; } - .column.is-offset-8-desktop { - margin-left: 66.66667%; } - .column.is-9-desktop { - flex: none; - width: 75%; } - .column.is-offset-9-desktop { - margin-left: 75%; } - .column.is-10-desktop { - flex: none; - width: 83.33333%; } - .column.is-offset-10-desktop { - margin-left: 83.33333%; } - .column.is-11-desktop { - flex: none; - width: 91.66667%; } - .column.is-offset-11-desktop { - margin-left: 91.66667%; } - .column.is-12-desktop { - flex: none; - width: 100%; } - .column.is-offset-12-desktop { - margin-left: 100%; } } - @media screen and (min-width: 1280px) { - .column.is-narrow-widescreen { - flex: none; } - .column.is-full-widescreen { - flex: none; - width: 100%; } - .column.is-three-quarters-widescreen { - flex: none; - width: 75%; } - .column.is-two-thirds-widescreen { - flex: none; - width: 66.6666%; } - .column.is-half-widescreen { - flex: none; - width: 50%; } - .column.is-one-third-widescreen { - flex: none; - width: 33.3333%; } - .column.is-one-quarter-widescreen { - flex: none; - width: 25%; } - .column.is-one-fifth-widescreen { - flex: none; - width: 20%; } - .column.is-two-fifths-widescreen { - flex: none; - width: 40%; } - .column.is-three-fifths-widescreen { - flex: none; - width: 60%; } - .column.is-four-fifths-widescreen { - flex: none; - width: 80%; } - .column.is-offset-three-quarters-widescreen { - margin-left: 75%; } - .column.is-offset-two-thirds-widescreen { - margin-left: 66.6666%; } - .column.is-offset-half-widescreen { - margin-left: 50%; } - .column.is-offset-one-third-widescreen { - margin-left: 33.3333%; } - .column.is-offset-one-quarter-widescreen { - margin-left: 25%; } - .column.is-offset-one-fifth-widescreen { - margin-left: 20%; } - .column.is-offset-two-fifths-widescreen { - margin-left: 40%; } - .column.is-offset-three-fifths-widescreen { - margin-left: 60%; } - .column.is-offset-four-fifths-widescreen { - margin-left: 80%; } - .column.is-1-widescreen { - flex: none; - width: 8.33333%; } - .column.is-offset-1-widescreen { - margin-left: 8.33333%; } - .column.is-2-widescreen { - flex: none; - width: 16.66667%; } - .column.is-offset-2-widescreen { - margin-left: 16.66667%; } - .column.is-3-widescreen { - flex: none; - width: 25%; } - .column.is-offset-3-widescreen { - margin-left: 25%; } - .column.is-4-widescreen { - flex: none; - width: 33.33333%; } - .column.is-offset-4-widescreen { - margin-left: 33.33333%; } - .column.is-5-widescreen { - flex: none; - width: 41.66667%; } - .column.is-offset-5-widescreen { - margin-left: 41.66667%; } - .column.is-6-widescreen { - flex: none; - width: 50%; } - .column.is-offset-6-widescreen { - margin-left: 50%; } - .column.is-7-widescreen { - flex: none; - width: 58.33333%; } - .column.is-offset-7-widescreen { - margin-left: 58.33333%; } - .column.is-8-widescreen { - flex: none; - width: 66.66667%; } - .column.is-offset-8-widescreen { - margin-left: 66.66667%; } - .column.is-9-widescreen { - flex: none; - width: 75%; } - .column.is-offset-9-widescreen { - margin-left: 75%; } - .column.is-10-widescreen { - flex: none; - width: 83.33333%; } - .column.is-offset-10-widescreen { - margin-left: 83.33333%; } - .column.is-11-widescreen { - flex: none; - width: 91.66667%; } - .column.is-offset-11-widescreen { - margin-left: 91.66667%; } - .column.is-12-widescreen { - flex: none; - width: 100%; } - .column.is-offset-12-widescreen { - margin-left: 100%; } } - @media screen and (min-width: 1472px) { - .column.is-narrow-fullhd { - flex: none; } - .column.is-full-fullhd { - flex: none; - width: 100%; } - .column.is-three-quarters-fullhd { - flex: none; - width: 75%; } - .column.is-two-thirds-fullhd { - flex: none; - width: 66.6666%; } - .column.is-half-fullhd { - flex: none; - width: 50%; } - .column.is-one-third-fullhd { - flex: none; - width: 33.3333%; } - .column.is-one-quarter-fullhd { - flex: none; - width: 25%; } - .column.is-one-fifth-fullhd { - flex: none; - width: 20%; } - .column.is-two-fifths-fullhd { - flex: none; - width: 40%; } - .column.is-three-fifths-fullhd { - flex: none; - width: 60%; } - .column.is-four-fifths-fullhd { - flex: none; - width: 80%; } - .column.is-offset-three-quarters-fullhd { - margin-left: 75%; } - .column.is-offset-two-thirds-fullhd { - margin-left: 66.6666%; } - .column.is-offset-half-fullhd { - margin-left: 50%; } - .column.is-offset-one-third-fullhd { - margin-left: 33.3333%; } - .column.is-offset-one-quarter-fullhd { - margin-left: 25%; } - .column.is-offset-one-fifth-fullhd { - margin-left: 20%; } - .column.is-offset-two-fifths-fullhd { - margin-left: 40%; } - .column.is-offset-three-fifths-fullhd { - margin-left: 60%; } - .column.is-offset-four-fifths-fullhd { - margin-left: 80%; } - .column.is-1-fullhd { - flex: none; - width: 8.33333%; } - .column.is-offset-1-fullhd { - margin-left: 8.33333%; } - .column.is-2-fullhd { - flex: none; - width: 16.66667%; } - .column.is-offset-2-fullhd { - margin-left: 16.66667%; } - .column.is-3-fullhd { - flex: none; - width: 25%; } - .column.is-offset-3-fullhd { - margin-left: 25%; } - .column.is-4-fullhd { - flex: none; - width: 33.33333%; } - .column.is-offset-4-fullhd { - margin-left: 33.33333%; } - .column.is-5-fullhd { - flex: none; - width: 41.66667%; } - .column.is-offset-5-fullhd { - margin-left: 41.66667%; } - .column.is-6-fullhd { - flex: none; - width: 50%; } - .column.is-offset-6-fullhd { - margin-left: 50%; } - .column.is-7-fullhd { - flex: none; - width: 58.33333%; } - .column.is-offset-7-fullhd { - margin-left: 58.33333%; } - .column.is-8-fullhd { - flex: none; - width: 66.66667%; } - .column.is-offset-8-fullhd { - margin-left: 66.66667%; } - .column.is-9-fullhd { - flex: none; - width: 75%; } - .column.is-offset-9-fullhd { - margin-left: 75%; } - .column.is-10-fullhd { - flex: none; - width: 83.33333%; } - .column.is-offset-10-fullhd { - margin-left: 83.33333%; } - .column.is-11-fullhd { - flex: none; - width: 91.66667%; } - .column.is-offset-11-fullhd { - margin-left: 91.66667%; } - .column.is-12-fullhd { - flex: none; - width: 100%; } - .column.is-offset-12-fullhd { - margin-left: 100%; } } - -.columns { - margin-left: -0.75rem; - margin-right: -0.75rem; - margin-top: -0.75rem; } - .columns:last-child { - margin-bottom: -0.75rem; } - .columns:not(:last-child) { - margin-bottom: calc(1.5rem - 0.75rem); } - .columns.is-centered { - justify-content: center; } - .columns.is-gapless { - margin-left: 0; - margin-right: 0; - margin-top: 0; } - .columns.is-gapless > .column { - margin: 0; - padding: 0 !important; } - .columns.is-gapless:not(:last-child) { - margin-bottom: 1.5rem; } - .columns.is-gapless:last-child { - margin-bottom: 0; } - .columns.is-mobile { - display: flex; } - .columns.is-multiline { - flex-wrap: wrap; } - .columns.is-vcentered { - align-items: center; } - @media screen and (min-width: 769px), print { - .columns:not(.is-desktop) { - display: flex; } } - @media screen and (min-width: 1088px) { - .columns.is-desktop { - display: flex; } } - -.columns.is-variable { - --columnGap: 0.75rem; - margin-left: calc(-1 * var(--columnGap)); - margin-right: calc(-1 * var(--columnGap)); } - .columns.is-variable .column { - padding-left: var(--columnGap); - padding-right: var(--columnGap); } - .columns.is-variable.is-0 { - --columnGap: 0rem; } - .columns.is-variable.is-1 { - --columnGap: 0.25rem; } - .columns.is-variable.is-2 { - --columnGap: 0.5rem; } - .columns.is-variable.is-3 { - --columnGap: 0.75rem; } - .columns.is-variable.is-4 { - --columnGap: 1rem; } - .columns.is-variable.is-5 { - --columnGap: 1.25rem; } - .columns.is-variable.is-6 { - --columnGap: 1.5rem; } - .columns.is-variable.is-7 { - --columnGap: 1.75rem; } - .columns.is-variable.is-8 { - --columnGap: 2rem; } - -.tile { - align-items: stretch; - display: block; - flex-basis: 0; - flex-grow: 1; - flex-shrink: 1; - min-height: min-content; } - .tile.is-ancestor { - margin-left: -0.75rem; - margin-right: -0.75rem; - margin-top: -0.75rem; } - .tile.is-ancestor:last-child { - margin-bottom: -0.75rem; } - .tile.is-ancestor:not(:last-child) { - margin-bottom: 0.75rem; } - .tile.is-child { - margin: 0 !important; } - .tile.is-parent { - padding: 0.75rem; } - .tile.is-vertical { - flex-direction: column; } - .tile.is-vertical > .tile.is-child:not(:last-child) { - margin-bottom: 1.5rem !important; } - @media screen and (min-width: 769px), print { - .tile:not(.is-child) { - display: flex; } - .tile.is-1 { - flex: none; - width: 8.33333%; } - .tile.is-2 { - flex: none; - width: 16.66667%; } - .tile.is-3 { - flex: none; - width: 25%; } - .tile.is-4 { - flex: none; - width: 33.33333%; } - .tile.is-5 { - flex: none; - width: 41.66667%; } - .tile.is-6 { - flex: none; - width: 50%; } - .tile.is-7 { - flex: none; - width: 58.33333%; } - .tile.is-8 { - flex: none; - width: 66.66667%; } - .tile.is-9 { - flex: none; - width: 75%; } - .tile.is-10 { - flex: none; - width: 83.33333%; } - .tile.is-11 { - flex: none; - width: 91.66667%; } - .tile.is-12 { - flex: none; - width: 100%; } } - -.hero { - align-items: stretch; - display: flex; - flex-direction: column; - justify-content: space-between; } - .hero .navbar { - background: none; } - .hero .tabs ul { - border-bottom: none; } - .hero.is-white { - background-color: white; - color: #0a0a0a; } - .hero.is-white a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-white strong { - color: inherit; } - .hero.is-white .title { - color: #0a0a0a; } - .hero.is-white .subtitle { - color: rgba(10, 10, 10, 0.9); } - .hero.is-white .subtitle a:not(.button), - .hero.is-white .subtitle strong { - color: #0a0a0a; } - @media screen and (max-width: 1087px) { - .hero.is-white .navbar-menu { - background-color: white; } } - .hero.is-white .navbar-item, - .hero.is-white .navbar-link { - color: rgba(10, 10, 10, 0.7); } - .hero.is-white a.navbar-item:hover, .hero.is-white a.navbar-item.is-active, - .hero.is-white .navbar-link:hover, - .hero.is-white .navbar-link.is-active { - background-color: #f2f2f2; - color: #0a0a0a; } - .hero.is-white .tabs a { - color: #0a0a0a; - opacity: 0.9; } - .hero.is-white .tabs a:hover { - opacity: 1; } - .hero.is-white .tabs li.is-active a { - opacity: 1; } - .hero.is-white .tabs.is-boxed a, .hero.is-white .tabs.is-toggle a { - color: #0a0a0a; } - .hero.is-white .tabs.is-boxed a:hover, .hero.is-white .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-white .tabs.is-boxed li.is-active a, .hero.is-white .tabs.is-boxed li.is-active a:hover, .hero.is-white .tabs.is-toggle li.is-active a, .hero.is-white .tabs.is-toggle li.is-active a:hover { - background-color: #0a0a0a; - border-color: #0a0a0a; - color: white; } - .hero.is-white.is-bold { - background-image: linear-gradient(141deg, #e6e6e6 0%, white 71%, white 100%); } - @media screen and (max-width: 768px) { - .hero.is-white.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #e6e6e6 0%, white 71%, white 100%); } } - .hero.is-black { - background-color: #0a0a0a; - color: white; } - .hero.is-black a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-black strong { - color: inherit; } - .hero.is-black .title { - color: white; } - .hero.is-black .subtitle { - color: rgba(255, 255, 255, 0.9); } - .hero.is-black .subtitle a:not(.button), - .hero.is-black .subtitle strong { - color: white; } - @media screen and (max-width: 1087px) { - .hero.is-black .navbar-menu { - background-color: #0a0a0a; } } - .hero.is-black .navbar-item, - .hero.is-black .navbar-link { - color: rgba(255, 255, 255, 0.7); } - .hero.is-black a.navbar-item:hover, .hero.is-black a.navbar-item.is-active, - .hero.is-black .navbar-link:hover, - .hero.is-black .navbar-link.is-active { - background-color: black; - color: white; } - .hero.is-black .tabs a { - color: white; - opacity: 0.9; } - .hero.is-black .tabs a:hover { - opacity: 1; } - .hero.is-black .tabs li.is-active a { - opacity: 1; } - .hero.is-black .tabs.is-boxed a, .hero.is-black .tabs.is-toggle a { - color: white; } - .hero.is-black .tabs.is-boxed a:hover, .hero.is-black .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-black .tabs.is-boxed li.is-active a, .hero.is-black .tabs.is-boxed li.is-active a:hover, .hero.is-black .tabs.is-toggle li.is-active a, .hero.is-black .tabs.is-toggle li.is-active a:hover { - background-color: white; - border-color: white; - color: #0a0a0a; } - .hero.is-black.is-bold { - background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); } - @media screen and (max-width: 768px) { - .hero.is-black.is-bold .navbar-menu { - background-image: linear-gradient(141deg, black 0%, #0a0a0a 71%, #181616 100%); } } - .hero.is-light { - background-color: whitesmoke; - color: #363636; } - .hero.is-light a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-light strong { - color: inherit; } - .hero.is-light .title { - color: #363636; } - .hero.is-light .subtitle { - color: rgba(54, 54, 54, 0.9); } - .hero.is-light .subtitle a:not(.button), - .hero.is-light .subtitle strong { - color: #363636; } - @media screen and (max-width: 1087px) { - .hero.is-light .navbar-menu { - background-color: whitesmoke; } } - .hero.is-light .navbar-item, - .hero.is-light .navbar-link { - color: rgba(54, 54, 54, 0.7); } - .hero.is-light a.navbar-item:hover, .hero.is-light a.navbar-item.is-active, - .hero.is-light .navbar-link:hover, - .hero.is-light .navbar-link.is-active { - background-color: #e8e8e8; - color: #363636; } - .hero.is-light .tabs a { - color: #363636; - opacity: 0.9; } - .hero.is-light .tabs a:hover { - opacity: 1; } - .hero.is-light .tabs li.is-active a { - opacity: 1; } - .hero.is-light .tabs.is-boxed a, .hero.is-light .tabs.is-toggle a { - color: #363636; } - .hero.is-light .tabs.is-boxed a:hover, .hero.is-light .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-light .tabs.is-boxed li.is-active a, .hero.is-light .tabs.is-boxed li.is-active a:hover, .hero.is-light .tabs.is-toggle li.is-active a, .hero.is-light .tabs.is-toggle li.is-active a:hover { - background-color: #363636; - border-color: #363636; - color: whitesmoke; } - .hero.is-light.is-bold { - background-image: linear-gradient(141deg, #dfd8d9 0%, whitesmoke 71%, white 100%); } - @media screen and (max-width: 768px) { - .hero.is-light.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #dfd8d9 0%, whitesmoke 71%, white 100%); } } - .hero.is-dark { - background-color: #363636; - color: whitesmoke; } - .hero.is-dark a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-dark strong { - color: inherit; } - .hero.is-dark .title { - color: whitesmoke; } - .hero.is-dark .subtitle { - color: rgba(245, 245, 245, 0.9); } - .hero.is-dark .subtitle a:not(.button), - .hero.is-dark .subtitle strong { - color: whitesmoke; } - @media screen and (max-width: 1087px) { - .hero.is-dark .navbar-menu { - background-color: #363636; } } - .hero.is-dark .navbar-item, - .hero.is-dark .navbar-link { - color: rgba(245, 245, 245, 0.7); } - .hero.is-dark a.navbar-item:hover, .hero.is-dark a.navbar-item.is-active, - .hero.is-dark .navbar-link:hover, - .hero.is-dark .navbar-link.is-active { - background-color: #292929; - color: whitesmoke; } - .hero.is-dark .tabs a { - color: whitesmoke; - opacity: 0.9; } - .hero.is-dark .tabs a:hover { - opacity: 1; } - .hero.is-dark .tabs li.is-active a { - opacity: 1; } - .hero.is-dark .tabs.is-boxed a, .hero.is-dark .tabs.is-toggle a { - color: whitesmoke; } - .hero.is-dark .tabs.is-boxed a:hover, .hero.is-dark .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-dark .tabs.is-boxed li.is-active a, .hero.is-dark .tabs.is-boxed li.is-active a:hover, .hero.is-dark .tabs.is-toggle li.is-active a, .hero.is-dark .tabs.is-toggle li.is-active a:hover { - background-color: whitesmoke; - border-color: whitesmoke; - color: #363636; } - .hero.is-dark.is-bold { - background-image: linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%); } - @media screen and (max-width: 768px) { - .hero.is-dark.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #1f191a 0%, #363636 71%, #46403f 100%); } } - .hero.is-primary { - background-color: #00d1b2; - color: #fff; } - .hero.is-primary a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-primary strong { - color: inherit; } - .hero.is-primary .title { - color: #fff; } - .hero.is-primary .subtitle { - color: rgba(255, 255, 255, 0.9); } - .hero.is-primary .subtitle a:not(.button), - .hero.is-primary .subtitle strong { - color: #fff; } - @media screen and (max-width: 1087px) { - .hero.is-primary .navbar-menu { - background-color: #00d1b2; } } - .hero.is-primary .navbar-item, - .hero.is-primary .navbar-link { - color: rgba(255, 255, 255, 0.7); } - .hero.is-primary a.navbar-item:hover, .hero.is-primary a.navbar-item.is-active, - .hero.is-primary .navbar-link:hover, - .hero.is-primary .navbar-link.is-active { - background-color: #00b89c; - color: #fff; } - .hero.is-primary .tabs a { - color: #fff; - opacity: 0.9; } - .hero.is-primary .tabs a:hover { - opacity: 1; } - .hero.is-primary .tabs li.is-active a { - opacity: 1; } - .hero.is-primary .tabs.is-boxed a, .hero.is-primary .tabs.is-toggle a { - color: #fff; } - .hero.is-primary .tabs.is-boxed a:hover, .hero.is-primary .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-primary .tabs.is-boxed li.is-active a, .hero.is-primary .tabs.is-boxed li.is-active a:hover, .hero.is-primary .tabs.is-toggle li.is-active a, .hero.is-primary .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #00d1b2; } - .hero.is-primary.is-bold { - background-image: linear-gradient(141deg, #009e6c 0%, #00d1b2 71%, #00e7eb 100%); } - @media screen and (max-width: 768px) { - .hero.is-primary.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #009e6c 0%, #00d1b2 71%, #00e7eb 100%); } } - .hero.is-link { - background-color: #33B2E8; - color: #fff; } - .hero.is-link a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-link strong { - color: inherit; } - .hero.is-link .title { - color: #fff; } - .hero.is-link .subtitle { - color: rgba(255, 255, 255, 0.9); } - .hero.is-link .subtitle a:not(.button), - .hero.is-link .subtitle strong { - color: #fff; } - @media screen and (max-width: 1087px) { - .hero.is-link .navbar-menu { - background-color: #33B2E8; } } - .hero.is-link .navbar-item, - .hero.is-link .navbar-link { - color: rgba(255, 255, 255, 0.7); } - .hero.is-link a.navbar-item:hover, .hero.is-link a.navbar-item.is-active, - .hero.is-link .navbar-link:hover, - .hero.is-link .navbar-link.is-active { - background-color: #1ca9e5; - color: #fff; } - .hero.is-link .tabs a { - color: #fff; - opacity: 0.9; } - .hero.is-link .tabs a:hover { - opacity: 1; } - .hero.is-link .tabs li.is-active a { - opacity: 1; } - .hero.is-link .tabs.is-boxed a, .hero.is-link .tabs.is-toggle a { - color: #fff; } - .hero.is-link .tabs.is-boxed a:hover, .hero.is-link .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-link .tabs.is-boxed li.is-active a, .hero.is-link .tabs.is-boxed li.is-active a:hover, .hero.is-link .tabs.is-toggle li.is-active a, .hero.is-link .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #33B2E8; } - .hero.is-link.is-bold { - background-image: linear-gradient(141deg, #0cc1dc 0%, #33B2E8 71%, #45a0f0 100%); } - @media screen and (max-width: 768px) { - .hero.is-link.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #0cc1dc 0%, #33B2E8 71%, #45a0f0 100%); } } - .hero.is-info { - background-color: #209cee; - color: #fff; } - .hero.is-info a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-info strong { - color: inherit; } - .hero.is-info .title { - color: #fff; } - .hero.is-info .subtitle { - color: rgba(255, 255, 255, 0.9); } - .hero.is-info .subtitle a:not(.button), - .hero.is-info .subtitle strong { - color: #fff; } - @media screen and (max-width: 1087px) { - .hero.is-info .navbar-menu { - background-color: #209cee; } } - .hero.is-info .navbar-item, - .hero.is-info .navbar-link { - color: rgba(255, 255, 255, 0.7); } - .hero.is-info a.navbar-item:hover, .hero.is-info a.navbar-item.is-active, - .hero.is-info .navbar-link:hover, - .hero.is-info .navbar-link.is-active { - background-color: #118fe4; - color: #fff; } - .hero.is-info .tabs a { - color: #fff; - opacity: 0.9; } - .hero.is-info .tabs a:hover { - opacity: 1; } - .hero.is-info .tabs li.is-active a { - opacity: 1; } - .hero.is-info .tabs.is-boxed a, .hero.is-info .tabs.is-toggle a { - color: #fff; } - .hero.is-info .tabs.is-boxed a:hover, .hero.is-info .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-info .tabs.is-boxed li.is-active a, .hero.is-info .tabs.is-boxed li.is-active a:hover, .hero.is-info .tabs.is-toggle li.is-active a, .hero.is-info .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #209cee; } - .hero.is-info.is-bold { - background-image: linear-gradient(141deg, #04a6d7 0%, #209cee 71%, #3287f5 100%); } - @media screen and (max-width: 768px) { - .hero.is-info.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #04a6d7 0%, #209cee 71%, #3287f5 100%); } } - .hero.is-success { - background-color: #23d160; - color: #fff; } - .hero.is-success a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-success strong { - color: inherit; } - .hero.is-success .title { - color: #fff; } - .hero.is-success .subtitle { - color: rgba(255, 255, 255, 0.9); } - .hero.is-success .subtitle a:not(.button), - .hero.is-success .subtitle strong { - color: #fff; } - @media screen and (max-width: 1087px) { - .hero.is-success .navbar-menu { - background-color: #23d160; } } - .hero.is-success .navbar-item, - .hero.is-success .navbar-link { - color: rgba(255, 255, 255, 0.7); } - .hero.is-success a.navbar-item:hover, .hero.is-success a.navbar-item.is-active, - .hero.is-success .navbar-link:hover, - .hero.is-success .navbar-link.is-active { - background-color: #20bc56; - color: #fff; } - .hero.is-success .tabs a { - color: #fff; - opacity: 0.9; } - .hero.is-success .tabs a:hover { - opacity: 1; } - .hero.is-success .tabs li.is-active a { - opacity: 1; } - .hero.is-success .tabs.is-boxed a, .hero.is-success .tabs.is-toggle a { - color: #fff; } - .hero.is-success .tabs.is-boxed a:hover, .hero.is-success .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-success .tabs.is-boxed li.is-active a, .hero.is-success .tabs.is-boxed li.is-active a:hover, .hero.is-success .tabs.is-toggle li.is-active a, .hero.is-success .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #23d160; } - .hero.is-success.is-bold { - background-image: linear-gradient(141deg, #12af2f 0%, #23d160 71%, #2ce28a 100%); } - @media screen and (max-width: 768px) { - .hero.is-success.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #12af2f 0%, #23d160 71%, #2ce28a 100%); } } - .hero.is-warning { - background-color: #ffdd57; - color: rgba(0, 0, 0, 0.7); } - .hero.is-warning a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-warning strong { - color: inherit; } - .hero.is-warning .title { - color: rgba(0, 0, 0, 0.7); } - .hero.is-warning .subtitle { - color: rgba(0, 0, 0, 0.9); } - .hero.is-warning .subtitle a:not(.button), - .hero.is-warning .subtitle strong { - color: rgba(0, 0, 0, 0.7); } - @media screen and (max-width: 1087px) { - .hero.is-warning .navbar-menu { - background-color: #ffdd57; } } - .hero.is-warning .navbar-item, - .hero.is-warning .navbar-link { - color: rgba(0, 0, 0, 0.7); } - .hero.is-warning a.navbar-item:hover, .hero.is-warning a.navbar-item.is-active, - .hero.is-warning .navbar-link:hover, - .hero.is-warning .navbar-link.is-active { - background-color: #ffd83d; - color: rgba(0, 0, 0, 0.7); } - .hero.is-warning .tabs a { - color: rgba(0, 0, 0, 0.7); - opacity: 0.9; } - .hero.is-warning .tabs a:hover { - opacity: 1; } - .hero.is-warning .tabs li.is-active a { - opacity: 1; } - .hero.is-warning .tabs.is-boxed a, .hero.is-warning .tabs.is-toggle a { - color: rgba(0, 0, 0, 0.7); } - .hero.is-warning .tabs.is-boxed a:hover, .hero.is-warning .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-warning .tabs.is-boxed li.is-active a, .hero.is-warning .tabs.is-boxed li.is-active a:hover, .hero.is-warning .tabs.is-toggle li.is-active a, .hero.is-warning .tabs.is-toggle li.is-active a:hover { - background-color: rgba(0, 0, 0, 0.7); - border-color: rgba(0, 0, 0, 0.7); - color: #ffdd57; } - .hero.is-warning.is-bold { - background-image: linear-gradient(141deg, #ffaf24 0%, #ffdd57 71%, #fffa70 100%); } - @media screen and (max-width: 768px) { - .hero.is-warning.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #ffaf24 0%, #ffdd57 71%, #fffa70 100%); } } - .hero.is-danger { - background-color: #ff3860; - color: #fff; } - .hero.is-danger a:not(.button):not(.dropdown-item):not(.tag), - .hero.is-danger strong { - color: inherit; } - .hero.is-danger .title { - color: #fff; } - .hero.is-danger .subtitle { - color: rgba(255, 255, 255, 0.9); } - .hero.is-danger .subtitle a:not(.button), - .hero.is-danger .subtitle strong { - color: #fff; } - @media screen and (max-width: 1087px) { - .hero.is-danger .navbar-menu { - background-color: #ff3860; } } - .hero.is-danger .navbar-item, - .hero.is-danger .navbar-link { - color: rgba(255, 255, 255, 0.7); } - .hero.is-danger a.navbar-item:hover, .hero.is-danger a.navbar-item.is-active, - .hero.is-danger .navbar-link:hover, - .hero.is-danger .navbar-link.is-active { - background-color: #ff1f4b; - color: #fff; } - .hero.is-danger .tabs a { - color: #fff; - opacity: 0.9; } - .hero.is-danger .tabs a:hover { - opacity: 1; } - .hero.is-danger .tabs li.is-active a { - opacity: 1; } - .hero.is-danger .tabs.is-boxed a, .hero.is-danger .tabs.is-toggle a { - color: #fff; } - .hero.is-danger .tabs.is-boxed a:hover, .hero.is-danger .tabs.is-toggle a:hover { - background-color: rgba(10, 10, 10, 0.1); } - .hero.is-danger .tabs.is-boxed li.is-active a, .hero.is-danger .tabs.is-boxed li.is-active a:hover, .hero.is-danger .tabs.is-toggle li.is-active a, .hero.is-danger .tabs.is-toggle li.is-active a:hover { - background-color: #fff; - border-color: #fff; - color: #ff3860; } - .hero.is-danger.is-bold { - background-image: linear-gradient(141deg, #ff0561 0%, #ff3860 71%, #ff5257 100%); } - @media screen and (max-width: 768px) { - .hero.is-danger.is-bold .navbar-menu { - background-image: linear-gradient(141deg, #ff0561 0%, #ff3860 71%, #ff5257 100%); } } - .hero.is-small .hero-body { - padding-bottom: 1.5rem; - padding-top: 1.5rem; } - @media screen and (min-width: 769px), print { - .hero.is-medium .hero-body { - padding-bottom: 9rem; - padding-top: 9rem; } } - @media screen and (min-width: 769px), print { - .hero.is-large .hero-body { - padding-bottom: 18rem; - padding-top: 18rem; } } - .hero.is-halfheight .hero-body, .hero.is-fullheight .hero-body { - align-items: center; - display: flex; } - .hero.is-halfheight .hero-body > .container, .hero.is-fullheight .hero-body > .container { - flex-grow: 1; - flex-shrink: 1; } - .hero.is-halfheight { - min-height: 50vh; } - .hero.is-fullheight { - min-height: 100vh; } - -.hero-video { - overflow: hidden; } - .hero-video video { - left: 50%; - min-height: 100%; - min-width: 100%; - position: absolute; - top: 50%; - transform: translate3d(-50%, -50%, 0); } - .hero-video.is-transparent { - opacity: 0.3; } - @media screen and (max-width: 768px) { - .hero-video { - display: none; } } - -.hero-buttons { - margin-top: 1.5rem; } - @media screen and (max-width: 768px) { - .hero-buttons .button { - display: flex; } - .hero-buttons .button:not(:last-child) { - margin-bottom: 0.75rem; } } - @media screen and (min-width: 769px), print { - .hero-buttons { - display: flex; - justify-content: center; } - .hero-buttons .button:not(:last-child) { - margin-right: 1.5rem; } } - -.hero-head, -.hero-foot { - flex-grow: 0; - flex-shrink: 0; } - -.hero-body { - flex-grow: 1; - flex-shrink: 0; - padding: 3rem 1.5rem; } - -.section { - padding: 3rem 1.5rem; } - @media screen and (min-width: 1088px) { - .section.is-medium { - padding: 9rem 1.5rem; } - .section.is-large { - padding: 18rem 1.5rem; } } - -.footer { - background-color: #fafafa; - padding: 3rem 1.5rem 6rem; } - -.box-link-shadow:hover, .box-link-shadow:focus { - box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px #33B2E8; } - -.box-link-shadow:active { - box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.2), 0 0 0 1px #33B2E8; } - -/*! - * Font Awesome Free 5.3.1 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - */ -.fa, -.fas, -.far, -.fal, -.fab { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - display: inline-block; - font-style: normal; - font-variant: normal; - text-rendering: auto; - line-height: 1; } - -.fa-lg { - font-size: 1.33333em; - line-height: 0.75em; - vertical-align: -.0667em; } - -.fa-xs { - font-size: .75em; } - -.fa-sm { - font-size: .875em; } - -.fa-1x { - font-size: 1em; } - -.fa-2x { - font-size: 2em; } - -.fa-3x { - font-size: 3em; } - -.fa-4x { - font-size: 4em; } - -.fa-5x { - font-size: 5em; } - -.fa-6x { - font-size: 6em; } - -.fa-7x { - font-size: 7em; } - -.fa-8x { - font-size: 8em; } - -.fa-9x { - font-size: 9em; } - -.fa-10x { - font-size: 10em; } - -.fa-fw { - text-align: center; - width: 1.25em; } - -.fa-ul { - list-style-type: none; - margin-left: 2.5em; - padding-left: 0; } - .fa-ul > li { - position: relative; } - -.fa-li { - left: -2em; - position: absolute; - text-align: center; - width: 2em; - line-height: inherit; } - -.fa-border { - border: solid 0.08em #eee; - border-radius: .1em; - padding: .2em .25em .15em; } - -.fa-pull-left { - float: left; } - -.fa-pull-right { - float: right; } - -.fa.fa-pull-left, -.fas.fa-pull-left, -.far.fa-pull-left, -.fal.fa-pull-left, -.fab.fa-pull-left { - margin-right: .3em; } - -.fa.fa-pull-right, -.fas.fa-pull-right, -.far.fa-pull-right, -.fal.fa-pull-right, -.fab.fa-pull-right { - margin-left: .3em; } - -.fa-spin { - animation: fa-spin 2s infinite linear; } - -.fa-pulse { - animation: fa-spin 1s infinite steps(8); } - -@keyframes fa-spin { - 0% { - transform: rotate(0deg); } - 100% { - transform: rotate(360deg); } } - -.fa-rotate-90 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; - transform: rotate(90deg); } - -.fa-rotate-180 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; - transform: rotate(180deg); } - -.fa-rotate-270 { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; - transform: rotate(270deg); } - -.fa-flip-horizontal { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; - transform: scale(-1, 1); } - -.fa-flip-vertical { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; - transform: scale(1, -1); } - -.fa-flip-horizontal.fa-flip-vertical { - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; - transform: scale(-1, -1); } - -:root .fa-rotate-90, -:root .fa-rotate-180, -:root .fa-rotate-270, -:root .fa-flip-horizontal, -:root .fa-flip-vertical { - filter: none; } - -.fa-stack { - display: inline-block; - height: 2em; - line-height: 2em; - position: relative; - vertical-align: middle; - width: 2em; } - -.fa-stack-1x, -.fa-stack-2x { - left: 0; - position: absolute; - text-align: center; - width: 100%; } - -.fa-stack-1x { - line-height: inherit; } - -.fa-stack-2x { - font-size: 2em; } - -.fa-inverse { - color: #fff; } - -/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen -readers do not read off random characters that represent icons */ -.fa-500px:before { - content: "\f26e"; } - -.fa-accessible-icon:before { - content: "\f368"; } - -.fa-accusoft:before { - content: "\f369"; } - -.fa-ad:before { - content: "\f641"; } - -.fa-address-book:before { - content: "\f2b9"; } - -.fa-address-card:before { - content: "\f2bb"; } - -.fa-adjust:before { - content: "\f042"; } - -.fa-adn:before { - content: "\f170"; } - -.fa-adversal:before { - content: "\f36a"; } - -.fa-affiliatetheme:before { - content: "\f36b"; } - -.fa-air-freshener:before { - content: "\f5d0"; } - -.fa-algolia:before { - content: "\f36c"; } - -.fa-align-center:before { - content: "\f037"; } - -.fa-align-justify:before { - content: "\f039"; } - -.fa-align-left:before { - content: "\f036"; } - -.fa-align-right:before { - content: "\f038"; } - -.fa-alipay:before { - content: "\f642"; } - -.fa-allergies:before { - content: "\f461"; } - -.fa-amazon:before { - content: "\f270"; } - -.fa-amazon-pay:before { - content: "\f42c"; } - -.fa-ambulance:before { - content: "\f0f9"; } - -.fa-american-sign-language-interpreting:before { - content: "\f2a3"; } - -.fa-amilia:before { - content: "\f36d"; } - -.fa-anchor:before { - content: "\f13d"; } - -.fa-android:before { - content: "\f17b"; } - -.fa-angellist:before { - content: "\f209"; } - -.fa-angle-double-down:before { - content: "\f103"; } - -.fa-angle-double-left:before { - content: "\f100"; } - -.fa-angle-double-right:before { - content: "\f101"; } - -.fa-angle-double-up:before { - content: "\f102"; } - -.fa-angle-down:before { - content: "\f107"; } - -.fa-angle-left:before { - content: "\f104"; } - -.fa-angle-right:before { - content: "\f105"; } - -.fa-angle-up:before { - content: "\f106"; } - -.fa-angry:before { - content: "\f556"; } - -.fa-angrycreative:before { - content: "\f36e"; } - -.fa-angular:before { - content: "\f420"; } - -.fa-ankh:before { - content: "\f644"; } - -.fa-app-store:before { - content: "\f36f"; } - -.fa-app-store-ios:before { - content: "\f370"; } - -.fa-apper:before { - content: "\f371"; } - -.fa-apple:before { - content: "\f179"; } - -.fa-apple-alt:before { - content: "\f5d1"; } - -.fa-apple-pay:before { - content: "\f415"; } - -.fa-archive:before { - content: "\f187"; } - -.fa-archway:before { - content: "\f557"; } - -.fa-arrow-alt-circle-down:before { - content: "\f358"; } - -.fa-arrow-alt-circle-left:before { - content: "\f359"; } - -.fa-arrow-alt-circle-right:before { - content: "\f35a"; } - -.fa-arrow-alt-circle-up:before { - content: "\f35b"; } - -.fa-arrow-circle-down:before { - content: "\f0ab"; } - -.fa-arrow-circle-left:before { - content: "\f0a8"; } - -.fa-arrow-circle-right:before { - content: "\f0a9"; } - -.fa-arrow-circle-up:before { - content: "\f0aa"; } - -.fa-arrow-down:before { - content: "\f063"; } - -.fa-arrow-left:before { - content: "\f060"; } - -.fa-arrow-right:before { - content: "\f061"; } - -.fa-arrow-up:before { - content: "\f062"; } - -.fa-arrows-alt:before { - content: "\f0b2"; } - -.fa-arrows-alt-h:before { - content: "\f337"; } - -.fa-arrows-alt-v:before { - content: "\f338"; } - -.fa-assistive-listening-systems:before { - content: "\f2a2"; } - -.fa-asterisk:before { - content: "\f069"; } - -.fa-asymmetrik:before { - content: "\f372"; } - -.fa-at:before { - content: "\f1fa"; } - -.fa-atlas:before { - content: "\f558"; } - -.fa-atom:before { - content: "\f5d2"; } - -.fa-audible:before { - content: "\f373"; } - -.fa-audio-description:before { - content: "\f29e"; } - -.fa-autoprefixer:before { - content: "\f41c"; } - -.fa-avianex:before { - content: "\f374"; } - -.fa-aviato:before { - content: "\f421"; } - -.fa-award:before { - content: "\f559"; } - -.fa-aws:before { - content: "\f375"; } - -.fa-backspace:before { - content: "\f55a"; } - -.fa-backward:before { - content: "\f04a"; } - -.fa-balance-scale:before { - content: "\f24e"; } - -.fa-ban:before { - content: "\f05e"; } - -.fa-band-aid:before { - content: "\f462"; } - -.fa-bandcamp:before { - content: "\f2d5"; } - -.fa-barcode:before { - content: "\f02a"; } - -.fa-bars:before { - content: "\f0c9"; } - -.fa-baseball-ball:before { - content: "\f433"; } - -.fa-basketball-ball:before { - content: "\f434"; } - -.fa-bath:before { - content: "\f2cd"; } - -.fa-battery-empty:before { - content: "\f244"; } - -.fa-battery-full:before { - content: "\f240"; } - -.fa-battery-half:before { - content: "\f242"; } - -.fa-battery-quarter:before { - content: "\f243"; } - -.fa-battery-three-quarters:before { - content: "\f241"; } - -.fa-bed:before { - content: "\f236"; } - -.fa-beer:before { - content: "\f0fc"; } - -.fa-behance:before { - content: "\f1b4"; } - -.fa-behance-square:before { - content: "\f1b5"; } - -.fa-bell:before { - content: "\f0f3"; } - -.fa-bell-slash:before { - content: "\f1f6"; } - -.fa-bezier-curve:before { - content: "\f55b"; } - -.fa-bible:before { - content: "\f647"; } - -.fa-bicycle:before { - content: "\f206"; } - -.fa-bimobject:before { - content: "\f378"; } - -.fa-binoculars:before { - content: "\f1e5"; } - -.fa-birthday-cake:before { - content: "\f1fd"; } - -.fa-bitbucket:before { - content: "\f171"; } - -.fa-bitcoin:before { - content: "\f379"; } - -.fa-bity:before { - content: "\f37a"; } - -.fa-black-tie:before { - content: "\f27e"; } - -.fa-blackberry:before { - content: "\f37b"; } - -.fa-blender:before { - content: "\f517"; } - -.fa-blind:before { - content: "\f29d"; } - -.fa-blogger:before { - content: "\f37c"; } - -.fa-blogger-b:before { - content: "\f37d"; } - -.fa-bluetooth:before { - content: "\f293"; } - -.fa-bluetooth-b:before { - content: "\f294"; } - -.fa-bold:before { - content: "\f032"; } - -.fa-bolt:before { - content: "\f0e7"; } - -.fa-bomb:before { - content: "\f1e2"; } - -.fa-bone:before { - content: "\f5d7"; } - -.fa-bong:before { - content: "\f55c"; } - -.fa-book:before { - content: "\f02d"; } - -.fa-book-open:before { - content: "\f518"; } - -.fa-book-reader:before { - content: "\f5da"; } - -.fa-bookmark:before { - content: "\f02e"; } - -.fa-bowling-ball:before { - content: "\f436"; } - -.fa-box:before { - content: "\f466"; } - -.fa-box-open:before { - content: "\f49e"; } - -.fa-boxes:before { - content: "\f468"; } - -.fa-braille:before { - content: "\f2a1"; } - -.fa-brain:before { - content: "\f5dc"; } - -.fa-briefcase:before { - content: "\f0b1"; } - -.fa-briefcase-medical:before { - content: "\f469"; } - -.fa-broadcast-tower:before { - content: "\f519"; } - -.fa-broom:before { - content: "\f51a"; } - -.fa-brush:before { - content: "\f55d"; } - -.fa-btc:before { - content: "\f15a"; } - -.fa-bug:before { - content: "\f188"; } - -.fa-building:before { - content: "\f1ad"; } - -.fa-bullhorn:before { - content: "\f0a1"; } - -.fa-bullseye:before { - content: "\f140"; } - -.fa-burn:before { - content: "\f46a"; } - -.fa-buromobelexperte:before { - content: "\f37f"; } - -.fa-bus:before { - content: "\f207"; } - -.fa-bus-alt:before { - content: "\f55e"; } - -.fa-business-time:before { - content: "\f64a"; } - -.fa-buysellads:before { - content: "\f20d"; } - -.fa-calculator:before { - content: "\f1ec"; } - -.fa-calendar:before { - content: "\f133"; } - -.fa-calendar-alt:before { - content: "\f073"; } - -.fa-calendar-check:before { - content: "\f274"; } - -.fa-calendar-minus:before { - content: "\f272"; } - -.fa-calendar-plus:before { - content: "\f271"; } - -.fa-calendar-times:before { - content: "\f273"; } - -.fa-camera:before { - content: "\f030"; } - -.fa-camera-retro:before { - content: "\f083"; } - -.fa-cannabis:before { - content: "\f55f"; } - -.fa-capsules:before { - content: "\f46b"; } - -.fa-car:before { - content: "\f1b9"; } - -.fa-car-alt:before { - content: "\f5de"; } - -.fa-car-battery:before { - content: "\f5df"; } - -.fa-car-crash:before { - content: "\f5e1"; } - -.fa-car-side:before { - content: "\f5e4"; } - -.fa-caret-down:before { - content: "\f0d7"; } - -.fa-caret-left:before { - content: "\f0d9"; } - -.fa-caret-right:before { - content: "\f0da"; } - -.fa-caret-square-down:before { - content: "\f150"; } - -.fa-caret-square-left:before { - content: "\f191"; } - -.fa-caret-square-right:before { - content: "\f152"; } - -.fa-caret-square-up:before { - content: "\f151"; } - -.fa-caret-up:before { - content: "\f0d8"; } - -.fa-cart-arrow-down:before { - content: "\f218"; } - -.fa-cart-plus:before { - content: "\f217"; } - -.fa-cc-amazon-pay:before { - content: "\f42d"; } - -.fa-cc-amex:before { - content: "\f1f3"; } - -.fa-cc-apple-pay:before { - content: "\f416"; } - -.fa-cc-diners-club:before { - content: "\f24c"; } - -.fa-cc-discover:before { - content: "\f1f2"; } - -.fa-cc-jcb:before { - content: "\f24b"; } - -.fa-cc-mastercard:before { - content: "\f1f1"; } - -.fa-cc-paypal:before { - content: "\f1f4"; } - -.fa-cc-stripe:before { - content: "\f1f5"; } - -.fa-cc-visa:before { - content: "\f1f0"; } - -.fa-centercode:before { - content: "\f380"; } - -.fa-certificate:before { - content: "\f0a3"; } - -.fa-chalkboard:before { - content: "\f51b"; } - -.fa-chalkboard-teacher:before { - content: "\f51c"; } - -.fa-charging-station:before { - content: "\f5e7"; } - -.fa-chart-area:before { - content: "\f1fe"; } - -.fa-chart-bar:before { - content: "\f080"; } - -.fa-chart-line:before { - content: "\f201"; } - -.fa-chart-pie:before { - content: "\f200"; } - -.fa-check:before { - content: "\f00c"; } - -.fa-check-circle:before { - content: "\f058"; } - -.fa-check-double:before { - content: "\f560"; } - -.fa-check-square:before { - content: "\f14a"; } - -.fa-chess:before { - content: "\f439"; } - -.fa-chess-bishop:before { - content: "\f43a"; } - -.fa-chess-board:before { - content: "\f43c"; } - -.fa-chess-king:before { - content: "\f43f"; } - -.fa-chess-knight:before { - content: "\f441"; } - -.fa-chess-pawn:before { - content: "\f443"; } - -.fa-chess-queen:before { - content: "\f445"; } - -.fa-chess-rook:before { - content: "\f447"; } - -.fa-chevron-circle-down:before { - content: "\f13a"; } - -.fa-chevron-circle-left:before { - content: "\f137"; } - -.fa-chevron-circle-right:before { - content: "\f138"; } - -.fa-chevron-circle-up:before { - content: "\f139"; } - -.fa-chevron-down:before { - content: "\f078"; } - -.fa-chevron-left:before { - content: "\f053"; } - -.fa-chevron-right:before { - content: "\f054"; } - -.fa-chevron-up:before { - content: "\f077"; } - -.fa-child:before { - content: "\f1ae"; } - -.fa-chrome:before { - content: "\f268"; } - -.fa-church:before { - content: "\f51d"; } - -.fa-circle:before { - content: "\f111"; } - -.fa-circle-notch:before { - content: "\f1ce"; } - -.fa-city:before { - content: "\f64f"; } - -.fa-clipboard:before { - content: "\f328"; } - -.fa-clipboard-check:before { - content: "\f46c"; } - -.fa-clipboard-list:before { - content: "\f46d"; } - -.fa-clock:before { - content: "\f017"; } - -.fa-clone:before { - content: "\f24d"; } - -.fa-closed-captioning:before { - content: "\f20a"; } - -.fa-cloud:before { - content: "\f0c2"; } - -.fa-cloud-download-alt:before { - content: "\f381"; } - -.fa-cloud-upload-alt:before { - content: "\f382"; } - -.fa-cloudscale:before { - content: "\f383"; } - -.fa-cloudsmith:before { - content: "\f384"; } - -.fa-cloudversify:before { - content: "\f385"; } - -.fa-cocktail:before { - content: "\f561"; } - -.fa-code:before { - content: "\f121"; } - -.fa-code-branch:before { - content: "\f126"; } - -.fa-codepen:before { - content: "\f1cb"; } - -.fa-codiepie:before { - content: "\f284"; } - -.fa-coffee:before { - content: "\f0f4"; } - -.fa-cog:before { - content: "\f013"; } - -.fa-cogs:before { - content: "\f085"; } - -.fa-coins:before { - content: "\f51e"; } - -.fa-columns:before { - content: "\f0db"; } - -.fa-comment:before { - content: "\f075"; } - -.fa-comment-alt:before { - content: "\f27a"; } - -.fa-comment-dollar:before { - content: "\f651"; } - -.fa-comment-dots:before { - content: "\f4ad"; } - -.fa-comment-slash:before { - content: "\f4b3"; } - -.fa-comments:before { - content: "\f086"; } - -.fa-comments-dollar:before { - content: "\f653"; } - -.fa-compact-disc:before { - content: "\f51f"; } - -.fa-compass:before { - content: "\f14e"; } - -.fa-compress:before { - content: "\f066"; } - -.fa-concierge-bell:before { - content: "\f562"; } - -.fa-connectdevelop:before { - content: "\f20e"; } - -.fa-contao:before { - content: "\f26d"; } - -.fa-cookie:before { - content: "\f563"; } - -.fa-cookie-bite:before { - content: "\f564"; } - -.fa-copy:before { - content: "\f0c5"; } - -.fa-copyright:before { - content: "\f1f9"; } - -.fa-couch:before { - content: "\f4b8"; } - -.fa-cpanel:before { - content: "\f388"; } - -.fa-creative-commons:before { - content: "\f25e"; } - -.fa-creative-commons-by:before { - content: "\f4e7"; } - -.fa-creative-commons-nc:before { - content: "\f4e8"; } - -.fa-creative-commons-nc-eu:before { - content: "\f4e9"; } - -.fa-creative-commons-nc-jp:before { - content: "\f4ea"; } - -.fa-creative-commons-nd:before { - content: "\f4eb"; } - -.fa-creative-commons-pd:before { - content: "\f4ec"; } - -.fa-creative-commons-pd-alt:before { - content: "\f4ed"; } - -.fa-creative-commons-remix:before { - content: "\f4ee"; } - -.fa-creative-commons-sa:before { - content: "\f4ef"; } - -.fa-creative-commons-sampling:before { - content: "\f4f0"; } - -.fa-creative-commons-sampling-plus:before { - content: "\f4f1"; } - -.fa-creative-commons-share:before { - content: "\f4f2"; } - -.fa-credit-card:before { - content: "\f09d"; } - -.fa-crop:before { - content: "\f125"; } - -.fa-crop-alt:before { - content: "\f565"; } - -.fa-cross:before { - content: "\f654"; } - -.fa-crosshairs:before { - content: "\f05b"; } - -.fa-crow:before { - content: "\f520"; } - -.fa-crown:before { - content: "\f521"; } - -.fa-css3:before { - content: "\f13c"; } - -.fa-css3-alt:before { - content: "\f38b"; } - -.fa-cube:before { - content: "\f1b2"; } - -.fa-cubes:before { - content: "\f1b3"; } - -.fa-cut:before { - content: "\f0c4"; } - -.fa-cuttlefish:before { - content: "\f38c"; } - -.fa-d-and-d:before { - content: "\f38d"; } - -.fa-dashcube:before { - content: "\f210"; } - -.fa-database:before { - content: "\f1c0"; } - -.fa-deaf:before { - content: "\f2a4"; } - -.fa-delicious:before { - content: "\f1a5"; } - -.fa-deploydog:before { - content: "\f38e"; } - -.fa-deskpro:before { - content: "\f38f"; } - -.fa-desktop:before { - content: "\f108"; } - -.fa-deviantart:before { - content: "\f1bd"; } - -.fa-dharmachakra:before { - content: "\f655"; } - -.fa-diagnoses:before { - content: "\f470"; } - -.fa-dice:before { - content: "\f522"; } - -.fa-dice-five:before { - content: "\f523"; } - -.fa-dice-four:before { - content: "\f524"; } - -.fa-dice-one:before { - content: "\f525"; } - -.fa-dice-six:before { - content: "\f526"; } - -.fa-dice-three:before { - content: "\f527"; } - -.fa-dice-two:before { - content: "\f528"; } - -.fa-digg:before { - content: "\f1a6"; } - -.fa-digital-ocean:before { - content: "\f391"; } - -.fa-digital-tachograph:before { - content: "\f566"; } - -.fa-directions:before { - content: "\f5eb"; } - -.fa-discord:before { - content: "\f392"; } - -.fa-discourse:before { - content: "\f393"; } - -.fa-divide:before { - content: "\f529"; } - -.fa-dizzy:before { - content: "\f567"; } - -.fa-dna:before { - content: "\f471"; } - -.fa-dochub:before { - content: "\f394"; } - -.fa-docker:before { - content: "\f395"; } - -.fa-dollar-sign:before { - content: "\f155"; } - -.fa-dolly:before { - content: "\f472"; } - -.fa-dolly-flatbed:before { - content: "\f474"; } - -.fa-donate:before { - content: "\f4b9"; } - -.fa-door-closed:before { - content: "\f52a"; } - -.fa-door-open:before { - content: "\f52b"; } - -.fa-dot-circle:before { - content: "\f192"; } - -.fa-dove:before { - content: "\f4ba"; } - -.fa-download:before { - content: "\f019"; } - -.fa-draft2digital:before { - content: "\f396"; } - -.fa-drafting-compass:before { - content: "\f568"; } - -.fa-draw-polygon:before { - content: "\f5ee"; } - -.fa-dribbble:before { - content: "\f17d"; } - -.fa-dribbble-square:before { - content: "\f397"; } - -.fa-dropbox:before { - content: "\f16b"; } - -.fa-drum:before { - content: "\f569"; } - -.fa-drum-steelpan:before { - content: "\f56a"; } - -.fa-drupal:before { - content: "\f1a9"; } - -.fa-dumbbell:before { - content: "\f44b"; } - -.fa-dyalog:before { - content: "\f399"; } - -.fa-earlybirds:before { - content: "\f39a"; } - -.fa-ebay:before { - content: "\f4f4"; } - -.fa-edge:before { - content: "\f282"; } - -.fa-edit:before { - content: "\f044"; } - -.fa-eject:before { - content: "\f052"; } - -.fa-elementor:before { - content: "\f430"; } - -.fa-ellipsis-h:before { - content: "\f141"; } - -.fa-ellipsis-v:before { - content: "\f142"; } - -.fa-ello:before { - content: "\f5f1"; } - -.fa-ember:before { - content: "\f423"; } - -.fa-empire:before { - content: "\f1d1"; } - -.fa-envelope:before { - content: "\f0e0"; } - -.fa-envelope-open:before { - content: "\f2b6"; } - -.fa-envelope-open-text:before { - content: "\f658"; } - -.fa-envelope-square:before { - content: "\f199"; } - -.fa-envira:before { - content: "\f299"; } - -.fa-equals:before { - content: "\f52c"; } - -.fa-eraser:before { - content: "\f12d"; } - -.fa-erlang:before { - content: "\f39d"; } - -.fa-ethereum:before { - content: "\f42e"; } - -.fa-etsy:before { - content: "\f2d7"; } - -.fa-euro-sign:before { - content: "\f153"; } - -.fa-exchange-alt:before { - content: "\f362"; } - -.fa-exclamation:before { - content: "\f12a"; } - -.fa-exclamation-circle:before { - content: "\f06a"; } - -.fa-exclamation-triangle:before { - content: "\f071"; } - -.fa-expand:before { - content: "\f065"; } - -.fa-expand-arrows-alt:before { - content: "\f31e"; } - -.fa-expeditedssl:before { - content: "\f23e"; } - -.fa-external-link-alt:before { - content: "\f35d"; } - -.fa-external-link-square-alt:before { - content: "\f360"; } - -.fa-eye:before { - content: "\f06e"; } - -.fa-eye-dropper:before { - content: "\f1fb"; } - -.fa-eye-slash:before { - content: "\f070"; } - -.fa-facebook:before { - content: "\f09a"; } - -.fa-facebook-f:before { - content: "\f39e"; } - -.fa-facebook-messenger:before { - content: "\f39f"; } - -.fa-facebook-square:before { - content: "\f082"; } - -.fa-fast-backward:before { - content: "\f049"; } - -.fa-fast-forward:before { - content: "\f050"; } - -.fa-fax:before { - content: "\f1ac"; } - -.fa-feather:before { - content: "\f52d"; } - -.fa-feather-alt:before { - content: "\f56b"; } - -.fa-female:before { - content: "\f182"; } - -.fa-fighter-jet:before { - content: "\f0fb"; } - -.fa-file:before { - content: "\f15b"; } - -.fa-file-alt:before { - content: "\f15c"; } - -.fa-file-archive:before { - content: "\f1c6"; } - -.fa-file-audio:before { - content: "\f1c7"; } - -.fa-file-code:before { - content: "\f1c9"; } - -.fa-file-contract:before { - content: "\f56c"; } - -.fa-file-download:before { - content: "\f56d"; } - -.fa-file-excel:before { - content: "\f1c3"; } - -.fa-file-export:before { - content: "\f56e"; } - -.fa-file-image:before { - content: "\f1c5"; } - -.fa-file-import:before { - content: "\f56f"; } - -.fa-file-invoice:before { - content: "\f570"; } - -.fa-file-invoice-dollar:before { - content: "\f571"; } - -.fa-file-medical:before { - content: "\f477"; } - -.fa-file-medical-alt:before { - content: "\f478"; } - -.fa-file-pdf:before { - content: "\f1c1"; } - -.fa-file-powerpoint:before { - content: "\f1c4"; } - -.fa-file-prescription:before { - content: "\f572"; } - -.fa-file-signature:before { - content: "\f573"; } - -.fa-file-upload:before { - content: "\f574"; } - -.fa-file-video:before { - content: "\f1c8"; } - -.fa-file-word:before { - content: "\f1c2"; } - -.fa-fill:before { - content: "\f575"; } - -.fa-fill-drip:before { - content: "\f576"; } - -.fa-film:before { - content: "\f008"; } - -.fa-filter:before { - content: "\f0b0"; } - -.fa-fingerprint:before { - content: "\f577"; } - -.fa-fire:before { - content: "\f06d"; } - -.fa-fire-extinguisher:before { - content: "\f134"; } - -.fa-firefox:before { - content: "\f269"; } - -.fa-first-aid:before { - content: "\f479"; } - -.fa-first-order:before { - content: "\f2b0"; } - -.fa-first-order-alt:before { - content: "\f50a"; } - -.fa-firstdraft:before { - content: "\f3a1"; } - -.fa-fish:before { - content: "\f578"; } - -.fa-flag:before { - content: "\f024"; } - -.fa-flag-checkered:before { - content: "\f11e"; } - -.fa-flask:before { - content: "\f0c3"; } - -.fa-flickr:before { - content: "\f16e"; } - -.fa-flipboard:before { - content: "\f44d"; } - -.fa-flushed:before { - content: "\f579"; } - -.fa-fly:before { - content: "\f417"; } - -.fa-folder:before { - content: "\f07b"; } - -.fa-folder-minus:before { - content: "\f65d"; } - -.fa-folder-open:before { - content: "\f07c"; } - -.fa-folder-plus:before { - content: "\f65e"; } - -.fa-font:before { - content: "\f031"; } - -.fa-font-awesome:before { - content: "\f2b4"; } - -.fa-font-awesome-alt:before { - content: "\f35c"; } - -.fa-font-awesome-flag:before { - content: "\f425"; } - -.fa-font-awesome-logo-full:before { - content: "\f4e6"; } - -.fa-fonticons:before { - content: "\f280"; } - -.fa-fonticons-fi:before { - content: "\f3a2"; } - -.fa-football-ball:before { - content: "\f44e"; } - -.fa-fort-awesome:before { - content: "\f286"; } - -.fa-fort-awesome-alt:before { - content: "\f3a3"; } - -.fa-forumbee:before { - content: "\f211"; } - -.fa-forward:before { - content: "\f04e"; } - -.fa-foursquare:before { - content: "\f180"; } - -.fa-free-code-camp:before { - content: "\f2c5"; } - -.fa-freebsd:before { - content: "\f3a4"; } - -.fa-frog:before { - content: "\f52e"; } - -.fa-frown:before { - content: "\f119"; } - -.fa-frown-open:before { - content: "\f57a"; } - -.fa-fulcrum:before { - content: "\f50b"; } - -.fa-funnel-dollar:before { - content: "\f662"; } - -.fa-futbol:before { - content: "\f1e3"; } - -.fa-galactic-republic:before { - content: "\f50c"; } - -.fa-galactic-senate:before { - content: "\f50d"; } - -.fa-gamepad:before { - content: "\f11b"; } - -.fa-gas-pump:before { - content: "\f52f"; } - -.fa-gavel:before { - content: "\f0e3"; } - -.fa-gem:before { - content: "\f3a5"; } - -.fa-genderless:before { - content: "\f22d"; } - -.fa-get-pocket:before { - content: "\f265"; } - -.fa-gg:before { - content: "\f260"; } - -.fa-gg-circle:before { - content: "\f261"; } - -.fa-gift:before { - content: "\f06b"; } - -.fa-git:before { - content: "\f1d3"; } - -.fa-git-square:before { - content: "\f1d2"; } - -.fa-github:before { - content: "\f09b"; } - -.fa-github-alt:before { - content: "\f113"; } - -.fa-github-square:before { - content: "\f092"; } - -.fa-gitkraken:before { - content: "\f3a6"; } - -.fa-gitlab:before { - content: "\f296"; } - -.fa-gitter:before { - content: "\f426"; } - -.fa-glass-martini:before { - content: "\f000"; } - -.fa-glass-martini-alt:before { - content: "\f57b"; } - -.fa-glasses:before { - content: "\f530"; } - -.fa-glide:before { - content: "\f2a5"; } - -.fa-glide-g:before { - content: "\f2a6"; } - -.fa-globe:before { - content: "\f0ac"; } - -.fa-globe-africa:before { - content: "\f57c"; } - -.fa-globe-americas:before { - content: "\f57d"; } - -.fa-globe-asia:before { - content: "\f57e"; } - -.fa-gofore:before { - content: "\f3a7"; } - -.fa-golf-ball:before { - content: "\f450"; } - -.fa-goodreads:before { - content: "\f3a8"; } - -.fa-goodreads-g:before { - content: "\f3a9"; } - -.fa-google:before { - content: "\f1a0"; } - -.fa-google-drive:before { - content: "\f3aa"; } - -.fa-google-play:before { - content: "\f3ab"; } - -.fa-google-plus:before { - content: "\f2b3"; } - -.fa-google-plus-g:before { - content: "\f0d5"; } - -.fa-google-plus-square:before { - content: "\f0d4"; } - -.fa-google-wallet:before { - content: "\f1ee"; } - -.fa-gopuram:before { - content: "\f664"; } - -.fa-graduation-cap:before { - content: "\f19d"; } - -.fa-gratipay:before { - content: "\f184"; } - -.fa-grav:before { - content: "\f2d6"; } - -.fa-greater-than:before { - content: "\f531"; } - -.fa-greater-than-equal:before { - content: "\f532"; } - -.fa-grimace:before { - content: "\f57f"; } - -.fa-grin:before { - content: "\f580"; } - -.fa-grin-alt:before { - content: "\f581"; } - -.fa-grin-beam:before { - content: "\f582"; } - -.fa-grin-beam-sweat:before { - content: "\f583"; } - -.fa-grin-hearts:before { - content: "\f584"; } - -.fa-grin-squint:before { - content: "\f585"; } - -.fa-grin-squint-tears:before { - content: "\f586"; } - -.fa-grin-stars:before { - content: "\f587"; } - -.fa-grin-tears:before { - content: "\f588"; } - -.fa-grin-tongue:before { - content: "\f589"; } - -.fa-grin-tongue-squint:before { - content: "\f58a"; } - -.fa-grin-tongue-wink:before { - content: "\f58b"; } - -.fa-grin-wink:before { - content: "\f58c"; } - -.fa-grip-horizontal:before { - content: "\f58d"; } - -.fa-grip-vertical:before { - content: "\f58e"; } - -.fa-gripfire:before { - content: "\f3ac"; } - -.fa-grunt:before { - content: "\f3ad"; } - -.fa-gulp:before { - content: "\f3ae"; } - -.fa-h-square:before { - content: "\f0fd"; } - -.fa-hacker-news:before { - content: "\f1d4"; } - -.fa-hacker-news-square:before { - content: "\f3af"; } - -.fa-hackerrank:before { - content: "\f5f7"; } - -.fa-hamsa:before { - content: "\f665"; } - -.fa-hand-holding:before { - content: "\f4bd"; } - -.fa-hand-holding-heart:before { - content: "\f4be"; } - -.fa-hand-holding-usd:before { - content: "\f4c0"; } - -.fa-hand-lizard:before { - content: "\f258"; } - -.fa-hand-paper:before { - content: "\f256"; } - -.fa-hand-peace:before { - content: "\f25b"; } - -.fa-hand-point-down:before { - content: "\f0a7"; } - -.fa-hand-point-left:before { - content: "\f0a5"; } - -.fa-hand-point-right:before { - content: "\f0a4"; } - -.fa-hand-point-up:before { - content: "\f0a6"; } - -.fa-hand-pointer:before { - content: "\f25a"; } - -.fa-hand-rock:before { - content: "\f255"; } - -.fa-hand-scissors:before { - content: "\f257"; } - -.fa-hand-spock:before { - content: "\f259"; } - -.fa-hands:before { - content: "\f4c2"; } - -.fa-hands-helping:before { - content: "\f4c4"; } - -.fa-handshake:before { - content: "\f2b5"; } - -.fa-hashtag:before { - content: "\f292"; } - -.fa-haykal:before { - content: "\f666"; } - -.fa-hdd:before { - content: "\f0a0"; } - -.fa-heading:before { - content: "\f1dc"; } - -.fa-headphones:before { - content: "\f025"; } - -.fa-headphones-alt:before { - content: "\f58f"; } - -.fa-headset:before { - content: "\f590"; } - -.fa-heart:before { - content: "\f004"; } - -.fa-heartbeat:before { - content: "\f21e"; } - -.fa-helicopter:before { - content: "\f533"; } - -.fa-highlighter:before { - content: "\f591"; } - -.fa-hips:before { - content: "\f452"; } - -.fa-hire-a-helper:before { - content: "\f3b0"; } - -.fa-history:before { - content: "\f1da"; } - -.fa-hockey-puck:before { - content: "\f453"; } - -.fa-home:before { - content: "\f015"; } - -.fa-hooli:before { - content: "\f427"; } - -.fa-hornbill:before { - content: "\f592"; } - -.fa-hospital:before { - content: "\f0f8"; } - -.fa-hospital-alt:before { - content: "\f47d"; } - -.fa-hospital-symbol:before { - content: "\f47e"; } - -.fa-hot-tub:before { - content: "\f593"; } - -.fa-hotel:before { - content: "\f594"; } - -.fa-hotjar:before { - content: "\f3b1"; } - -.fa-hourglass:before { - content: "\f254"; } - -.fa-hourglass-end:before { - content: "\f253"; } - -.fa-hourglass-half:before { - content: "\f252"; } - -.fa-hourglass-start:before { - content: "\f251"; } - -.fa-houzz:before { - content: "\f27c"; } - -.fa-html5:before { - content: "\f13b"; } - -.fa-hubspot:before { - content: "\f3b2"; } - -.fa-i-cursor:before { - content: "\f246"; } - -.fa-id-badge:before { - content: "\f2c1"; } - -.fa-id-card:before { - content: "\f2c2"; } - -.fa-id-card-alt:before { - content: "\f47f"; } - -.fa-image:before { - content: "\f03e"; } - -.fa-images:before { - content: "\f302"; } - -.fa-imdb:before { - content: "\f2d8"; } - -.fa-inbox:before { - content: "\f01c"; } - -.fa-indent:before { - content: "\f03c"; } - -.fa-industry:before { - content: "\f275"; } - -.fa-infinity:before { - content: "\f534"; } - -.fa-info:before { - content: "\f129"; } - -.fa-info-circle:before { - content: "\f05a"; } - -.fa-instagram:before { - content: "\f16d"; } - -.fa-internet-explorer:before { - content: "\f26b"; } - -.fa-ioxhost:before { - content: "\f208"; } - -.fa-italic:before { - content: "\f033"; } - -.fa-itunes:before { - content: "\f3b4"; } - -.fa-itunes-note:before { - content: "\f3b5"; } - -.fa-java:before { - content: "\f4e4"; } - -.fa-jedi:before { - content: "\f669"; } - -.fa-jedi-order:before { - content: "\f50e"; } - -.fa-jenkins:before { - content: "\f3b6"; } - -.fa-joget:before { - content: "\f3b7"; } - -.fa-joint:before { - content: "\f595"; } - -.fa-joomla:before { - content: "\f1aa"; } - -.fa-journal-whills:before { - content: "\f66a"; } - -.fa-js:before { - content: "\f3b8"; } - -.fa-js-square:before { - content: "\f3b9"; } - -.fa-jsfiddle:before { - content: "\f1cc"; } - -.fa-kaaba:before { - content: "\f66b"; } - -.fa-kaggle:before { - content: "\f5fa"; } - -.fa-key:before { - content: "\f084"; } - -.fa-keybase:before { - content: "\f4f5"; } - -.fa-keyboard:before { - content: "\f11c"; } - -.fa-keycdn:before { - content: "\f3ba"; } - -.fa-khanda:before { - content: "\f66d"; } - -.fa-kickstarter:before { - content: "\f3bb"; } - -.fa-kickstarter-k:before { - content: "\f3bc"; } - -.fa-kiss:before { - content: "\f596"; } - -.fa-kiss-beam:before { - content: "\f597"; } - -.fa-kiss-wink-heart:before { - content: "\f598"; } - -.fa-kiwi-bird:before { - content: "\f535"; } - -.fa-korvue:before { - content: "\f42f"; } - -.fa-landmark:before { - content: "\f66f"; } - -.fa-language:before { - content: "\f1ab"; } - -.fa-laptop:before { - content: "\f109"; } - -.fa-laptop-code:before { - content: "\f5fc"; } - -.fa-laravel:before { - content: "\f3bd"; } - -.fa-lastfm:before { - content: "\f202"; } - -.fa-lastfm-square:before { - content: "\f203"; } - -.fa-laugh:before { - content: "\f599"; } - -.fa-laugh-beam:before { - content: "\f59a"; } - -.fa-laugh-squint:before { - content: "\f59b"; } - -.fa-laugh-wink:before { - content: "\f59c"; } - -.fa-layer-group:before { - content: "\f5fd"; } - -.fa-leaf:before { - content: "\f06c"; } - -.fa-leanpub:before { - content: "\f212"; } - -.fa-lemon:before { - content: "\f094"; } - -.fa-less:before { - content: "\f41d"; } - -.fa-less-than:before { - content: "\f536"; } - -.fa-less-than-equal:before { - content: "\f537"; } - -.fa-level-down-alt:before { - content: "\f3be"; } - -.fa-level-up-alt:before { - content: "\f3bf"; } - -.fa-life-ring:before { - content: "\f1cd"; } - -.fa-lightbulb:before { - content: "\f0eb"; } - -.fa-line:before { - content: "\f3c0"; } - -.fa-link:before { - content: "\f0c1"; } - -.fa-linkedin:before { - content: "\f08c"; } - -.fa-linkedin-in:before { - content: "\f0e1"; } - -.fa-linode:before { - content: "\f2b8"; } - -.fa-linux:before { - content: "\f17c"; } - -.fa-lira-sign:before { - content: "\f195"; } - -.fa-list:before { - content: "\f03a"; } - -.fa-list-alt:before { - content: "\f022"; } - -.fa-list-ol:before { - content: "\f0cb"; } - -.fa-list-ul:before { - content: "\f0ca"; } - -.fa-location-arrow:before { - content: "\f124"; } - -.fa-lock:before { - content: "\f023"; } - -.fa-lock-open:before { - content: "\f3c1"; } - -.fa-long-arrow-alt-down:before { - content: "\f309"; } - -.fa-long-arrow-alt-left:before { - content: "\f30a"; } - -.fa-long-arrow-alt-right:before { - content: "\f30b"; } - -.fa-long-arrow-alt-up:before { - content: "\f30c"; } - -.fa-low-vision:before { - content: "\f2a8"; } - -.fa-luggage-cart:before { - content: "\f59d"; } - -.fa-lyft:before { - content: "\f3c3"; } - -.fa-magento:before { - content: "\f3c4"; } - -.fa-magic:before { - content: "\f0d0"; } - -.fa-magnet:before { - content: "\f076"; } - -.fa-mail-bulk:before { - content: "\f674"; } - -.fa-mailchimp:before { - content: "\f59e"; } - -.fa-male:before { - content: "\f183"; } - -.fa-mandalorian:before { - content: "\f50f"; } - -.fa-map:before { - content: "\f279"; } - -.fa-map-marked:before { - content: "\f59f"; } - -.fa-map-marked-alt:before { - content: "\f5a0"; } - -.fa-map-marker:before { - content: "\f041"; } - -.fa-map-marker-alt:before { - content: "\f3c5"; } - -.fa-map-pin:before { - content: "\f276"; } - -.fa-map-signs:before { - content: "\f277"; } - -.fa-markdown:before { - content: "\f60f"; } - -.fa-marker:before { - content: "\f5a1"; } - -.fa-mars:before { - content: "\f222"; } - -.fa-mars-double:before { - content: "\f227"; } - -.fa-mars-stroke:before { - content: "\f229"; } - -.fa-mars-stroke-h:before { - content: "\f22b"; } - -.fa-mars-stroke-v:before { - content: "\f22a"; } - -.fa-mastodon:before { - content: "\f4f6"; } - -.fa-maxcdn:before { - content: "\f136"; } - -.fa-medal:before { - content: "\f5a2"; } - -.fa-medapps:before { - content: "\f3c6"; } - -.fa-medium:before { - content: "\f23a"; } - -.fa-medium-m:before { - content: "\f3c7"; } - -.fa-medkit:before { - content: "\f0fa"; } - -.fa-medrt:before { - content: "\f3c8"; } - -.fa-meetup:before { - content: "\f2e0"; } - -.fa-megaport:before { - content: "\f5a3"; } - -.fa-meh:before { - content: "\f11a"; } - -.fa-meh-blank:before { - content: "\f5a4"; } - -.fa-meh-rolling-eyes:before { - content: "\f5a5"; } - -.fa-memory:before { - content: "\f538"; } - -.fa-menorah:before { - content: "\f676"; } - -.fa-mercury:before { - content: "\f223"; } - -.fa-microchip:before { - content: "\f2db"; } - -.fa-microphone:before { - content: "\f130"; } - -.fa-microphone-alt:before { - content: "\f3c9"; } - -.fa-microphone-alt-slash:before { - content: "\f539"; } - -.fa-microphone-slash:before { - content: "\f131"; } - -.fa-microscope:before { - content: "\f610"; } - -.fa-microsoft:before { - content: "\f3ca"; } - -.fa-minus:before { - content: "\f068"; } - -.fa-minus-circle:before { - content: "\f056"; } - -.fa-minus-square:before { - content: "\f146"; } - -.fa-mix:before { - content: "\f3cb"; } - -.fa-mixcloud:before { - content: "\f289"; } - -.fa-mizuni:before { - content: "\f3cc"; } - -.fa-mobile:before { - content: "\f10b"; } - -.fa-mobile-alt:before { - content: "\f3cd"; } - -.fa-modx:before { - content: "\f285"; } - -.fa-monero:before { - content: "\f3d0"; } - -.fa-money-bill:before { - content: "\f0d6"; } - -.fa-money-bill-alt:before { - content: "\f3d1"; } - -.fa-money-bill-wave:before { - content: "\f53a"; } - -.fa-money-bill-wave-alt:before { - content: "\f53b"; } - -.fa-money-check:before { - content: "\f53c"; } - -.fa-money-check-alt:before { - content: "\f53d"; } - -.fa-monument:before { - content: "\f5a6"; } - -.fa-moon:before { - content: "\f186"; } - -.fa-mortar-pestle:before { - content: "\f5a7"; } - -.fa-mosque:before { - content: "\f678"; } - -.fa-motorcycle:before { - content: "\f21c"; } - -.fa-mouse-pointer:before { - content: "\f245"; } - -.fa-music:before { - content: "\f001"; } - -.fa-napster:before { - content: "\f3d2"; } - -.fa-neos:before { - content: "\f612"; } - -.fa-neuter:before { - content: "\f22c"; } - -.fa-newspaper:before { - content: "\f1ea"; } - -.fa-nimblr:before { - content: "\f5a8"; } - -.fa-nintendo-switch:before { - content: "\f418"; } - -.fa-node:before { - content: "\f419"; } - -.fa-node-js:before { - content: "\f3d3"; } - -.fa-not-equal:before { - content: "\f53e"; } - -.fa-notes-medical:before { - content: "\f481"; } - -.fa-npm:before { - content: "\f3d4"; } - -.fa-ns8:before { - content: "\f3d5"; } - -.fa-nutritionix:before { - content: "\f3d6"; } - -.fa-object-group:before { - content: "\f247"; } - -.fa-object-ungroup:before { - content: "\f248"; } - -.fa-odnoklassniki:before { - content: "\f263"; } - -.fa-odnoklassniki-square:before { - content: "\f264"; } - -.fa-oil-can:before { - content: "\f613"; } - -.fa-old-republic:before { - content: "\f510"; } - -.fa-om:before { - content: "\f679"; } - -.fa-opencart:before { - content: "\f23d"; } - -.fa-openid:before { - content: "\f19b"; } - -.fa-opera:before { - content: "\f26a"; } - -.fa-optin-monster:before { - content: "\f23c"; } - -.fa-osi:before { - content: "\f41a"; } - -.fa-outdent:before { - content: "\f03b"; } - -.fa-page4:before { - content: "\f3d7"; } - -.fa-pagelines:before { - content: "\f18c"; } - -.fa-paint-brush:before { - content: "\f1fc"; } - -.fa-paint-roller:before { - content: "\f5aa"; } - -.fa-palette:before { - content: "\f53f"; } - -.fa-palfed:before { - content: "\f3d8"; } - -.fa-pallet:before { - content: "\f482"; } - -.fa-paper-plane:before { - content: "\f1d8"; } - -.fa-paperclip:before { - content: "\f0c6"; } - -.fa-parachute-box:before { - content: "\f4cd"; } - -.fa-paragraph:before { - content: "\f1dd"; } - -.fa-parking:before { - content: "\f540"; } - -.fa-passport:before { - content: "\f5ab"; } - -.fa-pastafarianism:before { - content: "\f67b"; } - -.fa-paste:before { - content: "\f0ea"; } - -.fa-patreon:before { - content: "\f3d9"; } - -.fa-pause:before { - content: "\f04c"; } - -.fa-pause-circle:before { - content: "\f28b"; } - -.fa-paw:before { - content: "\f1b0"; } - -.fa-paypal:before { - content: "\f1ed"; } - -.fa-peace:before { - content: "\f67c"; } - -.fa-pen:before { - content: "\f304"; } - -.fa-pen-alt:before { - content: "\f305"; } - -.fa-pen-fancy:before { - content: "\f5ac"; } - -.fa-pen-nib:before { - content: "\f5ad"; } - -.fa-pen-square:before { - content: "\f14b"; } - -.fa-pencil-alt:before { - content: "\f303"; } - -.fa-pencil-ruler:before { - content: "\f5ae"; } - -.fa-people-carry:before { - content: "\f4ce"; } - -.fa-percent:before { - content: "\f295"; } - -.fa-percentage:before { - content: "\f541"; } - -.fa-periscope:before { - content: "\f3da"; } - -.fa-phabricator:before { - content: "\f3db"; } - -.fa-phoenix-framework:before { - content: "\f3dc"; } - -.fa-phoenix-squadron:before { - content: "\f511"; } - -.fa-phone:before { - content: "\f095"; } - -.fa-phone-slash:before { - content: "\f3dd"; } - -.fa-phone-square:before { - content: "\f098"; } - -.fa-phone-volume:before { - content: "\f2a0"; } - -.fa-php:before { - content: "\f457"; } - -.fa-pied-piper:before { - content: "\f2ae"; } - -.fa-pied-piper-alt:before { - content: "\f1a8"; } - -.fa-pied-piper-hat:before { - content: "\f4e5"; } - -.fa-pied-piper-pp:before { - content: "\f1a7"; } - -.fa-piggy-bank:before { - content: "\f4d3"; } - -.fa-pills:before { - content: "\f484"; } - -.fa-pinterest:before { - content: "\f0d2"; } - -.fa-pinterest-p:before { - content: "\f231"; } - -.fa-pinterest-square:before { - content: "\f0d3"; } - -.fa-place-of-worship:before { - content: "\f67f"; } - -.fa-plane:before { - content: "\f072"; } - -.fa-plane-arrival:before { - content: "\f5af"; } - -.fa-plane-departure:before { - content: "\f5b0"; } - -.fa-play:before { - content: "\f04b"; } - -.fa-play-circle:before { - content: "\f144"; } - -.fa-playstation:before { - content: "\f3df"; } - -.fa-plug:before { - content: "\f1e6"; } - -.fa-plus:before { - content: "\f067"; } - -.fa-plus-circle:before { - content: "\f055"; } - -.fa-plus-square:before { - content: "\f0fe"; } - -.fa-podcast:before { - content: "\f2ce"; } - -.fa-poll:before { - content: "\f681"; } - -.fa-poll-h:before { - content: "\f682"; } - -.fa-poo:before { - content: "\f2fe"; } - -.fa-poop:before { - content: "\f619"; } - -.fa-portrait:before { - content: "\f3e0"; } - -.fa-pound-sign:before { - content: "\f154"; } - -.fa-power-off:before { - content: "\f011"; } - -.fa-pray:before { - content: "\f683"; } - -.fa-praying-hands:before { - content: "\f684"; } - -.fa-prescription:before { - content: "\f5b1"; } - -.fa-prescription-bottle:before { - content: "\f485"; } - -.fa-prescription-bottle-alt:before { - content: "\f486"; } - -.fa-print:before { - content: "\f02f"; } - -.fa-procedures:before { - content: "\f487"; } - -.fa-product-hunt:before { - content: "\f288"; } - -.fa-project-diagram:before { - content: "\f542"; } - -.fa-pushed:before { - content: "\f3e1"; } - -.fa-puzzle-piece:before { - content: "\f12e"; } - -.fa-python:before { - content: "\f3e2"; } - -.fa-qq:before { - content: "\f1d6"; } - -.fa-qrcode:before { - content: "\f029"; } - -.fa-question:before { - content: "\f128"; } - -.fa-question-circle:before { - content: "\f059"; } - -.fa-quidditch:before { - content: "\f458"; } - -.fa-quinscape:before { - content: "\f459"; } - -.fa-quora:before { - content: "\f2c4"; } - -.fa-quote-left:before { - content: "\f10d"; } - -.fa-quote-right:before { - content: "\f10e"; } - -.fa-quran:before { - content: "\f687"; } - -.fa-r-project:before { - content: "\f4f7"; } - -.fa-random:before { - content: "\f074"; } - -.fa-ravelry:before { - content: "\f2d9"; } - -.fa-react:before { - content: "\f41b"; } - -.fa-readme:before { - content: "\f4d5"; } - -.fa-rebel:before { - content: "\f1d0"; } - -.fa-receipt:before { - content: "\f543"; } - -.fa-recycle:before { - content: "\f1b8"; } - -.fa-red-river:before { - content: "\f3e3"; } - -.fa-reddit:before { - content: "\f1a1"; } - -.fa-reddit-alien:before { - content: "\f281"; } - -.fa-reddit-square:before { - content: "\f1a2"; } - -.fa-redo:before { - content: "\f01e"; } - -.fa-redo-alt:before { - content: "\f2f9"; } - -.fa-registered:before { - content: "\f25d"; } - -.fa-rendact:before { - content: "\f3e4"; } - -.fa-renren:before { - content: "\f18b"; } - -.fa-reply:before { - content: "\f3e5"; } - -.fa-reply-all:before { - content: "\f122"; } - -.fa-replyd:before { - content: "\f3e6"; } - -.fa-researchgate:before { - content: "\f4f8"; } - -.fa-resolving:before { - content: "\f3e7"; } - -.fa-retweet:before { - content: "\f079"; } - -.fa-rev:before { - content: "\f5b2"; } - -.fa-ribbon:before { - content: "\f4d6"; } - -.fa-road:before { - content: "\f018"; } - -.fa-robot:before { - content: "\f544"; } - -.fa-rocket:before { - content: "\f135"; } - -.fa-rocketchat:before { - content: "\f3e8"; } - -.fa-rockrms:before { - content: "\f3e9"; } - -.fa-route:before { - content: "\f4d7"; } - -.fa-rss:before { - content: "\f09e"; } - -.fa-rss-square:before { - content: "\f143"; } - -.fa-ruble-sign:before { - content: "\f158"; } - -.fa-ruler:before { - content: "\f545"; } - -.fa-ruler-combined:before { - content: "\f546"; } - -.fa-ruler-horizontal:before { - content: "\f547"; } - -.fa-ruler-vertical:before { - content: "\f548"; } - -.fa-rupee-sign:before { - content: "\f156"; } - -.fa-sad-cry:before { - content: "\f5b3"; } - -.fa-sad-tear:before { - content: "\f5b4"; } - -.fa-safari:before { - content: "\f267"; } - -.fa-sass:before { - content: "\f41e"; } - -.fa-save:before { - content: "\f0c7"; } - -.fa-schlix:before { - content: "\f3ea"; } - -.fa-school:before { - content: "\f549"; } - -.fa-screwdriver:before { - content: "\f54a"; } - -.fa-scribd:before { - content: "\f28a"; } - -.fa-search:before { - content: "\f002"; } - -.fa-search-dollar:before { - content: "\f688"; } - -.fa-search-location:before { - content: "\f689"; } - -.fa-search-minus:before { - content: "\f010"; } - -.fa-search-plus:before { - content: "\f00e"; } - -.fa-searchengin:before { - content: "\f3eb"; } - -.fa-seedling:before { - content: "\f4d8"; } - -.fa-sellcast:before { - content: "\f2da"; } - -.fa-sellsy:before { - content: "\f213"; } - -.fa-server:before { - content: "\f233"; } - -.fa-servicestack:before { - content: "\f3ec"; } - -.fa-shapes:before { - content: "\f61f"; } - -.fa-share:before { - content: "\f064"; } - -.fa-share-alt:before { - content: "\f1e0"; } - -.fa-share-alt-square:before { - content: "\f1e1"; } - -.fa-share-square:before { - content: "\f14d"; } - -.fa-shekel-sign:before { - content: "\f20b"; } - -.fa-shield-alt:before { - content: "\f3ed"; } - -.fa-ship:before { - content: "\f21a"; } - -.fa-shipping-fast:before { - content: "\f48b"; } - -.fa-shirtsinbulk:before { - content: "\f214"; } - -.fa-shoe-prints:before { - content: "\f54b"; } - -.fa-shopping-bag:before { - content: "\f290"; } - -.fa-shopping-basket:before { - content: "\f291"; } - -.fa-shopping-cart:before { - content: "\f07a"; } - -.fa-shopware:before { - content: "\f5b5"; } - -.fa-shower:before { - content: "\f2cc"; } - -.fa-shuttle-van:before { - content: "\f5b6"; } - -.fa-sign:before { - content: "\f4d9"; } - -.fa-sign-in-alt:before { - content: "\f2f6"; } - -.fa-sign-language:before { - content: "\f2a7"; } - -.fa-sign-out-alt:before { - content: "\f2f5"; } - -.fa-signal:before { - content: "\f012"; } - -.fa-signature:before { - content: "\f5b7"; } - -.fa-simplybuilt:before { - content: "\f215"; } - -.fa-sistrix:before { - content: "\f3ee"; } - -.fa-sitemap:before { - content: "\f0e8"; } - -.fa-sith:before { - content: "\f512"; } - -.fa-skull:before { - content: "\f54c"; } - -.fa-skyatlas:before { - content: "\f216"; } - -.fa-skype:before { - content: "\f17e"; } - -.fa-slack:before { - content: "\f198"; } - -.fa-slack-hash:before { - content: "\f3ef"; } - -.fa-sliders-h:before { - content: "\f1de"; } - -.fa-slideshare:before { - content: "\f1e7"; } - -.fa-smile:before { - content: "\f118"; } - -.fa-smile-beam:before { - content: "\f5b8"; } - -.fa-smile-wink:before { - content: "\f4da"; } - -.fa-smoking:before { - content: "\f48d"; } - -.fa-smoking-ban:before { - content: "\f54d"; } - -.fa-snapchat:before { - content: "\f2ab"; } - -.fa-snapchat-ghost:before { - content: "\f2ac"; } - -.fa-snapchat-square:before { - content: "\f2ad"; } - -.fa-snowflake:before { - content: "\f2dc"; } - -.fa-socks:before { - content: "\f696"; } - -.fa-solar-panel:before { - content: "\f5ba"; } - -.fa-sort:before { - content: "\f0dc"; } - -.fa-sort-alpha-down:before { - content: "\f15d"; } - -.fa-sort-alpha-up:before { - content: "\f15e"; } - -.fa-sort-amount-down:before { - content: "\f160"; } - -.fa-sort-amount-up:before { - content: "\f161"; } - -.fa-sort-down:before { - content: "\f0dd"; } - -.fa-sort-numeric-down:before { - content: "\f162"; } - -.fa-sort-numeric-up:before { - content: "\f163"; } - -.fa-sort-up:before { - content: "\f0de"; } - -.fa-soundcloud:before { - content: "\f1be"; } - -.fa-spa:before { - content: "\f5bb"; } - -.fa-space-shuttle:before { - content: "\f197"; } - -.fa-speakap:before { - content: "\f3f3"; } - -.fa-spinner:before { - content: "\f110"; } - -.fa-splotch:before { - content: "\f5bc"; } - -.fa-spotify:before { - content: "\f1bc"; } - -.fa-spray-can:before { - content: "\f5bd"; } - -.fa-square:before { - content: "\f0c8"; } - -.fa-square-full:before { - content: "\f45c"; } - -.fa-square-root-alt:before { - content: "\f698"; } - -.fa-squarespace:before { - content: "\f5be"; } - -.fa-stack-exchange:before { - content: "\f18d"; } - -.fa-stack-overflow:before { - content: "\f16c"; } - -.fa-stamp:before { - content: "\f5bf"; } - -.fa-star:before { - content: "\f005"; } - -.fa-star-and-crescent:before { - content: "\f699"; } - -.fa-star-half:before { - content: "\f089"; } - -.fa-star-half-alt:before { - content: "\f5c0"; } - -.fa-star-of-david:before { - content: "\f69a"; } - -.fa-star-of-life:before { - content: "\f621"; } - -.fa-staylinked:before { - content: "\f3f5"; } - -.fa-steam:before { - content: "\f1b6"; } - -.fa-steam-square:before { - content: "\f1b7"; } - -.fa-steam-symbol:before { - content: "\f3f6"; } - -.fa-step-backward:before { - content: "\f048"; } - -.fa-step-forward:before { - content: "\f051"; } - -.fa-stethoscope:before { - content: "\f0f1"; } - -.fa-sticker-mule:before { - content: "\f3f7"; } - -.fa-sticky-note:before { - content: "\f249"; } - -.fa-stop:before { - content: "\f04d"; } - -.fa-stop-circle:before { - content: "\f28d"; } - -.fa-stopwatch:before { - content: "\f2f2"; } - -.fa-store:before { - content: "\f54e"; } - -.fa-store-alt:before { - content: "\f54f"; } - -.fa-strava:before { - content: "\f428"; } - -.fa-stream:before { - content: "\f550"; } - -.fa-street-view:before { - content: "\f21d"; } - -.fa-strikethrough:before { - content: "\f0cc"; } - -.fa-stripe:before { - content: "\f429"; } - -.fa-stripe-s:before { - content: "\f42a"; } - -.fa-stroopwafel:before { - content: "\f551"; } - -.fa-studiovinari:before { - content: "\f3f8"; } - -.fa-stumbleupon:before { - content: "\f1a4"; } - -.fa-stumbleupon-circle:before { - content: "\f1a3"; } - -.fa-subscript:before { - content: "\f12c"; } - -.fa-subway:before { - content: "\f239"; } - -.fa-suitcase:before { - content: "\f0f2"; } - -.fa-suitcase-rolling:before { - content: "\f5c1"; } - -.fa-sun:before { - content: "\f185"; } - -.fa-superpowers:before { - content: "\f2dd"; } - -.fa-superscript:before { - content: "\f12b"; } - -.fa-supple:before { - content: "\f3f9"; } - -.fa-surprise:before { - content: "\f5c2"; } - -.fa-swatchbook:before { - content: "\f5c3"; } - -.fa-swimmer:before { - content: "\f5c4"; } - -.fa-swimming-pool:before { - content: "\f5c5"; } - -.fa-synagogue:before { - content: "\f69b"; } - -.fa-sync:before { - content: "\f021"; } - -.fa-sync-alt:before { - content: "\f2f1"; } - -.fa-syringe:before { - content: "\f48e"; } - -.fa-table:before { - content: "\f0ce"; } - -.fa-table-tennis:before { - content: "\f45d"; } - -.fa-tablet:before { - content: "\f10a"; } - -.fa-tablet-alt:before { - content: "\f3fa"; } - -.fa-tablets:before { - content: "\f490"; } - -.fa-tachometer-alt:before { - content: "\f3fd"; } - -.fa-tag:before { - content: "\f02b"; } - -.fa-tags:before { - content: "\f02c"; } - -.fa-tape:before { - content: "\f4db"; } - -.fa-tasks:before { - content: "\f0ae"; } - -.fa-taxi:before { - content: "\f1ba"; } - -.fa-teamspeak:before { - content: "\f4f9"; } - -.fa-teeth:before { - content: "\f62e"; } - -.fa-teeth-open:before { - content: "\f62f"; } - -.fa-telegram:before { - content: "\f2c6"; } - -.fa-telegram-plane:before { - content: "\f3fe"; } - -.fa-tencent-weibo:before { - content: "\f1d5"; } - -.fa-terminal:before { - content: "\f120"; } - -.fa-text-height:before { - content: "\f034"; } - -.fa-text-width:before { - content: "\f035"; } - -.fa-th:before { - content: "\f00a"; } - -.fa-th-large:before { - content: "\f009"; } - -.fa-th-list:before { - content: "\f00b"; } - -.fa-the-red-yeti:before { - content: "\f69d"; } - -.fa-theater-masks:before { - content: "\f630"; } - -.fa-themeco:before { - content: "\f5c6"; } - -.fa-themeisle:before { - content: "\f2b2"; } - -.fa-thermometer:before { - content: "\f491"; } - -.fa-thermometer-empty:before { - content: "\f2cb"; } - -.fa-thermometer-full:before { - content: "\f2c7"; } - -.fa-thermometer-half:before { - content: "\f2c9"; } - -.fa-thermometer-quarter:before { - content: "\f2ca"; } - -.fa-thermometer-three-quarters:before { - content: "\f2c8"; } - -.fa-thumbs-down:before { - content: "\f165"; } - -.fa-thumbs-up:before { - content: "\f164"; } - -.fa-thumbtack:before { - content: "\f08d"; } - -.fa-ticket-alt:before { - content: "\f3ff"; } - -.fa-times:before { - content: "\f00d"; } - -.fa-times-circle:before { - content: "\f057"; } - -.fa-tint:before { - content: "\f043"; } - -.fa-tint-slash:before { - content: "\f5c7"; } - -.fa-tired:before { - content: "\f5c8"; } - -.fa-toggle-off:before { - content: "\f204"; } - -.fa-toggle-on:before { - content: "\f205"; } - -.fa-toolbox:before { - content: "\f552"; } - -.fa-tooth:before { - content: "\f5c9"; } - -.fa-torah:before { - content: "\f6a0"; } - -.fa-torii-gate:before { - content: "\f6a1"; } - -.fa-trade-federation:before { - content: "\f513"; } - -.fa-trademark:before { - content: "\f25c"; } - -.fa-traffic-light:before { - content: "\f637"; } - -.fa-train:before { - content: "\f238"; } - -.fa-transgender:before { - content: "\f224"; } - -.fa-transgender-alt:before { - content: "\f225"; } - -.fa-trash:before { - content: "\f1f8"; } - -.fa-trash-alt:before { - content: "\f2ed"; } - -.fa-tree:before { - content: "\f1bb"; } - -.fa-trello:before { - content: "\f181"; } - -.fa-tripadvisor:before { - content: "\f262"; } - -.fa-trophy:before { - content: "\f091"; } - -.fa-truck:before { - content: "\f0d1"; } - -.fa-truck-loading:before { - content: "\f4de"; } - -.fa-truck-monster:before { - content: "\f63b"; } - -.fa-truck-moving:before { - content: "\f4df"; } - -.fa-truck-pickup:before { - content: "\f63c"; } - -.fa-tshirt:before { - content: "\f553"; } - -.fa-tty:before { - content: "\f1e4"; } - -.fa-tumblr:before { - content: "\f173"; } - -.fa-tumblr-square:before { - content: "\f174"; } - -.fa-tv:before { - content: "\f26c"; } - -.fa-twitch:before { - content: "\f1e8"; } - -.fa-twitter:before { - content: "\f099"; } - -.fa-twitter-square:before { - content: "\f081"; } - -.fa-typo3:before { - content: "\f42b"; } - -.fa-uber:before { - content: "\f402"; } - -.fa-uikit:before { - content: "\f403"; } - -.fa-umbrella:before { - content: "\f0e9"; } - -.fa-umbrella-beach:before { - content: "\f5ca"; } - -.fa-underline:before { - content: "\f0cd"; } - -.fa-undo:before { - content: "\f0e2"; } - -.fa-undo-alt:before { - content: "\f2ea"; } - -.fa-uniregistry:before { - content: "\f404"; } - -.fa-universal-access:before { - content: "\f29a"; } - -.fa-university:before { - content: "\f19c"; } - -.fa-unlink:before { - content: "\f127"; } - -.fa-unlock:before { - content: "\f09c"; } - -.fa-unlock-alt:before { - content: "\f13e"; } - -.fa-untappd:before { - content: "\f405"; } - -.fa-upload:before { - content: "\f093"; } - -.fa-usb:before { - content: "\f287"; } - -.fa-user:before { - content: "\f007"; } - -.fa-user-alt:before { - content: "\f406"; } - -.fa-user-alt-slash:before { - content: "\f4fa"; } - -.fa-user-astronaut:before { - content: "\f4fb"; } - -.fa-user-check:before { - content: "\f4fc"; } - -.fa-user-circle:before { - content: "\f2bd"; } - -.fa-user-clock:before { - content: "\f4fd"; } - -.fa-user-cog:before { - content: "\f4fe"; } - -.fa-user-edit:before { - content: "\f4ff"; } - -.fa-user-friends:before { - content: "\f500"; } - -.fa-user-graduate:before { - content: "\f501"; } - -.fa-user-lock:before { - content: "\f502"; } - -.fa-user-md:before { - content: "\f0f0"; } - -.fa-user-minus:before { - content: "\f503"; } - -.fa-user-ninja:before { - content: "\f504"; } - -.fa-user-plus:before { - content: "\f234"; } - -.fa-user-secret:before { - content: "\f21b"; } - -.fa-user-shield:before { - content: "\f505"; } - -.fa-user-slash:before { - content: "\f506"; } - -.fa-user-tag:before { - content: "\f507"; } - -.fa-user-tie:before { - content: "\f508"; } - -.fa-user-times:before { - content: "\f235"; } - -.fa-users:before { - content: "\f0c0"; } - -.fa-users-cog:before { - content: "\f509"; } - -.fa-ussunnah:before { - content: "\f407"; } - -.fa-utensil-spoon:before { - content: "\f2e5"; } - -.fa-utensils:before { - content: "\f2e7"; } - -.fa-vaadin:before { - content: "\f408"; } - -.fa-vector-square:before { - content: "\f5cb"; } - -.fa-venus:before { - content: "\f221"; } - -.fa-venus-double:before { - content: "\f226"; } - -.fa-venus-mars:before { - content: "\f228"; } - -.fa-viacoin:before { - content: "\f237"; } - -.fa-viadeo:before { - content: "\f2a9"; } - -.fa-viadeo-square:before { - content: "\f2aa"; } - -.fa-vial:before { - content: "\f492"; } - -.fa-vials:before { - content: "\f493"; } - -.fa-viber:before { - content: "\f409"; } - -.fa-video:before { - content: "\f03d"; } - -.fa-video-slash:before { - content: "\f4e2"; } - -.fa-vihara:before { - content: "\f6a7"; } - -.fa-vimeo:before { - content: "\f40a"; } - -.fa-vimeo-square:before { - content: "\f194"; } - -.fa-vimeo-v:before { - content: "\f27d"; } - -.fa-vine:before { - content: "\f1ca"; } - -.fa-vk:before { - content: "\f189"; } - -.fa-vnv:before { - content: "\f40b"; } - -.fa-volleyball-ball:before { - content: "\f45f"; } - -.fa-volume-down:before { - content: "\f027"; } - -.fa-volume-off:before { - content: "\f026"; } - -.fa-volume-up:before { - content: "\f028"; } - -.fa-vuejs:before { - content: "\f41f"; } - -.fa-walking:before { - content: "\f554"; } - -.fa-wallet:before { - content: "\f555"; } - -.fa-warehouse:before { - content: "\f494"; } - -.fa-weebly:before { - content: "\f5cc"; } - -.fa-weibo:before { - content: "\f18a"; } - -.fa-weight:before { - content: "\f496"; } - -.fa-weight-hanging:before { - content: "\f5cd"; } - -.fa-weixin:before { - content: "\f1d7"; } - -.fa-whatsapp:before { - content: "\f232"; } - -.fa-whatsapp-square:before { - content: "\f40c"; } - -.fa-wheelchair:before { - content: "\f193"; } - -.fa-whmcs:before { - content: "\f40d"; } - -.fa-wifi:before { - content: "\f1eb"; } - -.fa-wikipedia-w:before { - content: "\f266"; } - -.fa-window-close:before { - content: "\f410"; } - -.fa-window-maximize:before { - content: "\f2d0"; } - -.fa-window-minimize:before { - content: "\f2d1"; } - -.fa-window-restore:before { - content: "\f2d2"; } - -.fa-windows:before { - content: "\f17a"; } - -.fa-wine-glass:before { - content: "\f4e3"; } - -.fa-wine-glass-alt:before { - content: "\f5ce"; } - -.fa-wix:before { - content: "\f5cf"; } - -.fa-wolf-pack-battalion:before { - content: "\f514"; } - -.fa-won-sign:before { - content: "\f159"; } - -.fa-wordpress:before { - content: "\f19a"; } - -.fa-wordpress-simple:before { - content: "\f411"; } - -.fa-wpbeginner:before { - content: "\f297"; } - -.fa-wpexplorer:before { - content: "\f2de"; } - -.fa-wpforms:before { - content: "\f298"; } - -.fa-wrench:before { - content: "\f0ad"; } - -.fa-x-ray:before { - content: "\f497"; } - -.fa-xbox:before { - content: "\f412"; } - -.fa-xing:before { - content: "\f168"; } - -.fa-xing-square:before { - content: "\f169"; } - -.fa-y-combinator:before { - content: "\f23b"; } - -.fa-yahoo:before { - content: "\f19e"; } - -.fa-yandex:before { - content: "\f413"; } - -.fa-yandex-international:before { - content: "\f414"; } - -.fa-yelp:before { - content: "\f1e9"; } - -.fa-yen-sign:before { - content: "\f157"; } - -.fa-yin-yang:before { - content: "\f6ad"; } - -.fa-yoast:before { - content: "\f2b1"; } - -.fa-youtube:before { - content: "\f167"; } - -.fa-youtube-square:before { - content: "\f431"; } - -.fa-zhihu:before { - content: "\f63f"; } - -.sr-only { - border: 0; - clip: rect(0, 0, 0, 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; } - -.sr-only-focusable:active, .sr-only-focusable:focus { - clip: auto; - height: auto; - margin: 0; - overflow: visible; - position: static; - width: auto; } - -/*! - * Font Awesome Free 5.3.1 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - */ -@font-face { - font-family: 'Font Awesome 5 Free'; - font-style: normal; - font-weight: 400; - src: url("webfonts/fa-regular-400.eot"); - src: url("webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("webfonts/fa-regular-400.woff2") format("woff2"), url("webfonts/fa-regular-400.woff") format("woff"), url("webfonts/fa-regular-400.ttf") format("truetype"), url("webfonts/fa-regular-400.svg#fontawesome") format("svg"); } - -.far { - font-family: 'Font Awesome 5 Free'; - font-weight: 400; } +/* +Error: File to import not found or unreadable: bulma/sass/utilities/initial-variables. + Load paths: + C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/Configuration/SassFrameworks/bourbon + C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/Configuration/SassFrameworks/neat + C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/Configuration/SassFrameworks/base + on line 1 of C:\Users\jkefel\Documents\Hg\scm-manager\scm-ui\styles\scm.scss + +1: @import "bulma/sass/utilities/initial-variables"; +2: @import "bulma/sass/utilities/functions"; +3: +4: +5: $blue: #33B2E8; +6: $mint: #11dfd0; + +Backtrace: +C:\Users\jkefel\Documents\Hg\scm-manager\scm-ui\styles\scm.scss:1 +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/import_node.rb:67:in `rescue in import' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/import_node.rb:45:in `import' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/import_node.rb:28:in `imported_file' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/import_node.rb:37:in `css_import?' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:314:in `visit_import' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/base.rb:36:in `visit' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:162:in `block in visit' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/stack.rb:79:in `block in with_base' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/stack.rb:135:in `with_frame' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/stack.rb:79:in `with_base' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:162:in `visit' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/base.rb:52:in `block in visit_children' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/base.rb:52:in `map' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/base.rb:52:in `visit_children' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:171:in `block in visit_children' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:183:in `with_environment' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:170:in `visit_children' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/base.rb:36:in `block in visit' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:190:in `visit_root' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/base.rb:36:in `visit' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:161:in `visit' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/visitors/perform.rb:10:in `visit' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/root_node.rb:36:in `css_tree' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/tree/root_node.rb:20:in `render' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/engine.rb:290:in `render' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/exec/sass_scss.rb:400:in `run' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/exec/sass_scss.rb:63:in `process_result' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/exec/base.rb:52:in `parse' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/lib/sass/exec/base.rb:19:in `parse!' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/lib/ruby/gems/2.4.0/gems/sass-3.5.3/bin/sass:13:in `' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/bin/sass:23:in `load' +C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/ruby/bin/sass:23:in `
' +*/ +body:before { + white-space: pre; + font-family: monospace; + content: "Error: File to import not found or unreadable: bulma/sass/utilities/initial-variables.\A Load paths:\A C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/Configuration/SassFrameworks/bourbon\A C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/Configuration/SassFrameworks/neat\A C:/Program Files/Adobe/Adobe Dreamweaver CC 2019/Configuration/SassFrameworks/base\A on line 1 of C:\Users\jkefel\Documents\Hg\scm-manager\scm-ui\styles\scm.scss\A \A 1: @import \"bulma/sass/utilities/initial-variables\";\A 2: @import \"bulma/sass/utilities/functions\";\A 3: \A 4: \A 5: $blue: #33B2E8;\A 6: $mint: #11dfd0;"; } diff --git a/scm-ui/styles/scm.scss b/scm-ui/styles/scm.scss index 4d306df6ad..9d65bbe26f 100644 --- a/scm-ui/styles/scm.scss +++ b/scm-ui/styles/scm.scss @@ -1,8 +1,8 @@ @import "bulma/sass/utilities/initial-variables"; @import "bulma/sass/utilities/functions"; - -$blue: #33B2E8; +$blue: #33b2e8; +$mint: #11dfd0; // $footer-background-color @@ -27,6 +27,14 @@ $blue: #33B2E8; padding: 0 0 0 3.8em !important; } +.is-word-break { + -webkit-hyphens: auto; + -moz-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; + word-break: break-all; +} + .main { min-height: calc(100vh - 260px); } @@ -43,15 +51,238 @@ $blue: #33B2E8; &:hover, &:focus { box-shadow: $box-link-hover-shadow; - } + } &:active { box-shadow: $box-link-active-shadow; } } - @import "@fortawesome/fontawesome-free/scss/fontawesome.scss"; $fa-font-path: "webfonts"; @import "@fortawesome/fontawesome-free/scss/solid.scss"; @import "diff2html/dist/diff2html"; + +// NEW STYLES + +//typography +.subtitle { + color: #666; +} +.has-border-white { + border-color: #fff !important; +} +// buttons +.button { + padding-left: 1.5em; + padding-right: 1.5em; + height: 2.5rem; + + &.is-primary { + background-color: $mint; + } +} + +//border around options +.has-border-around { + border-top: 1px solid #eee; + border-left: 1px solid #eee; + border-right: 1px solid #eee; + border-bottom: 1px solid #eee; +} + +// multiline Columns +.columns.is-multiline { + .column.is-half { + width: calc(50% - 0.75rem); + max-height: 120px; + + &:nth-child(odd) { + margin-right: 1.5rem; + } + } + @media screen and (max-width: 768px) { + .column.is-half { + width: 100%; + + &:nth-child(odd) { + margin-right: 0; + } + } + } +} + +.media { + .media-content { + width: calc(50% - 0.75rem); + .shorten-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } +} + +// tables +.table { + width: 100%; + td { + border-color: #eee; + padding: 1rem; + } +} + +// card tables +.card-table { + border-collapse: separate; + border-spacing: 0px 5px; + + tr { + a { + color: #363636; + } + &:hover { + td { + background-color: whitesmoke; + &:nth-child(4) { + background-color: #e1e1e1; + } + } + a { + color: $blue; + } + } + } + td { + border-bottom: 1px solid whitesmoke; + background-color: #fafafa; + padding: 1em 1.25em; + &:first-child { + border-left: 3px solid $mint; + } + &:nth-child(4) { + background-color: whitesmoke; + } + } + &.is-hoverable tbody tr:not(.is-selected):hover { + background-color: whitesmoke; + } + thead th { + background-color: transparent; + border: none; + } +} + +// forms +.field:not(.is-grouped) { + margin-bottom: 1rem; +} +.input, +.textarea { + /*background-color: whitesmoke;*/ + border-color: #98d8f3; + box-shadow: none; +} + +// pagination +.pagination-next, +.pagination-link, +.pagination-ellipsis { + padding-left: 1.5em; + padding-right: 1.5em; + height: 2.5rem; +} +.pagination-previous, +.pagination-next { + min-width: 6.75em; +} + +// dark hero colors +.hero.is-dark { + background-color: #002e4b; + background-image: url(../images/scmManagerHero.jpg); + background-size: cover; + background-position: top center; + + .tabs.is-boxed li.is-active a, + .tabs.is-boxed li.is-active a:hover, + .tabs.is-toggle li.is-active a, + .tabs.is-toggle li.is-active a:hover { + background-color: #28b1e8; + border-color: #28b1e8; + color: #fff; + } +} + +// footer +.footer { + background-color: whitesmoke; +} + +// sidebar menu +.aside-background { + bottom: 0; + left: 50%; + position: absolute; + right: 0; + top: 0; + background-color: whitesmoke; +} +.menu { + div { + height: 100%; + /*border: 1px solid #eee;*/ + margin-bottom: 1rem; + } +} + +.menu-label { + color: #fff; + font-size: 1em; + font-weight: 600; + background-color: #bbb; + border-radius: 5px 5px 0 0; + padding: 0.5rem 1rem; + text-transform: none; + + &:last-child, + &:not(:last-child) { + margin-bottom: 0; + } +} +.menu div:first-child .menu-label { + background-color: $blue; +} +.menu-list { + a { + border-radius: 0; + color: #333; + padding: 1rem; + border-top: 1px solid #eee; + border-left: 1px solid #eee; + border-right: 1px solid #eee; + + &.is-active { + color: $blue; + background-color: #fff; + + &:before { + position: relative; + content: " "; + background: $blue; + height: 53px; + width: 2px; + display: block; + left: -17px; + float: left; + top: -16px; + } + } + } + > li:first-child > a { + border-top: none; + } + li:last-child > a { + border-bottom: 1px solid #eee; + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 9555ad66b5..7c7dec47ff 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -79,14 +79,14 @@ import sonia.scm.repository.spi.HookEventFacade; import sonia.scm.repository.xml.XmlRepositoryDAO; import sonia.scm.schedule.QuartzScheduler; import sonia.scm.schedule.Scheduler; +import sonia.scm.security.AccessTokenCookieIssuer; import sonia.scm.security.AuthorizationChangedEventProducer; import sonia.scm.security.CipherHandler; import sonia.scm.security.CipherUtil; import sonia.scm.security.ConfigurableLoginAttemptHandler; -import sonia.scm.security.DefaultJwtAccessTokenRefreshStrategy; +import sonia.scm.security.DefaultAccessTokenCookieIssuer; import sonia.scm.security.DefaultKeyGenerator; import sonia.scm.security.DefaultSecuritySystem; -import sonia.scm.security.JwtAccessTokenRefreshStrategy; import sonia.scm.security.KeyGenerator; import sonia.scm.security.LoginAttemptHandler; import sonia.scm.security.SecuritySystem; @@ -112,9 +112,7 @@ import sonia.scm.util.ScmConfigurationUtil; import sonia.scm.web.UserAgentParser; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.DefaultCGIExecutorFactory; -import sonia.scm.web.filter.AuthenticationFilter; import sonia.scm.web.filter.LoggingFilter; -import sonia.scm.web.protocol.HttpProtocolServlet; import sonia.scm.web.security.AdministrationContext; import sonia.scm.web.security.DefaultAdministrationContext; @@ -315,11 +313,10 @@ public class ScmServletModule extends ServletModule bind(TemplateEngineFactory.class); bind(ObjectMapper.class).toProvider(ObjectMapperProvider.class); - filter(HttpProtocolServlet.PATTERN).through(AuthenticationFilter.class); - // bind events // bind(LastModifiedUpdateListener.class); + bind(AccessTokenCookieIssuer.class).to(DefaultAccessTokenCookieIssuer.class); bind(PushStateDispatcher.class).toProvider(PushStateDispatcherProvider.class); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/FallbackExceptionMapper.java b/scm-webapp/src/main/java/sonia/scm/api/FallbackExceptionMapper.java index c687af4826..4815b22bdc 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/FallbackExceptionMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/FallbackExceptionMapper.java @@ -20,7 +20,7 @@ public class FallbackExceptionMapper implements ExceptionMapper { @Override public Response toResponse(Exception exception) { - logger.debug("map exception to status code 500", exception); + logger.warn("mapping unexpected {} to status code 500", exception.getClass().getName(), exception); ErrorDto errorDto = new ErrorDto(); errorDto.setMessage("internal server error"); errorDto.setContext(Collections.emptyList()); diff --git a/scm-webapp/src/main/java/sonia/scm/api/JsonParseExceptionMapper.java b/scm-webapp/src/main/java/sonia/scm/api/JsonParseExceptionMapper.java new file mode 100644 index 0000000000..dacecb350e --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/JsonParseExceptionMapper.java @@ -0,0 +1,35 @@ +package sonia.scm.api; + +import com.fasterxml.jackson.core.JsonParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import sonia.scm.api.v2.resources.ErrorDto; +import sonia.scm.web.VndMediaType; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import java.util.Collections; + +@Provider +public class JsonParseExceptionMapper implements ExceptionMapper { + + private static final Logger logger = LoggerFactory.getLogger(JsonParseExceptionMapper.class); + + private static final String ERROR_CODE = "2VRCrvpL71"; + + @Override + public Response toResponse(JsonParseException exception) { + logger.trace("got illegal json: {}", exception.getMessage()); + ErrorDto errorDto = new ErrorDto(); + errorDto.setMessage("illegal json content: " + exception.getMessage()); + errorDto.setContext(Collections.emptyList()); + errorDto.setErrorCode(ERROR_CODE); + errorDto.setTransactionId(MDC.get("transaction_id")); + return Response.status(Response.Status.BAD_REQUEST) + .entity(errorDto) + .type(VndMediaType.ERROR_TYPE) + .build(); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/StatusExceptionMapper.java b/scm-webapp/src/main/java/sonia/scm/api/rest/StatusExceptionMapper.java index 6f4978637e..1590154369 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/StatusExceptionMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/StatusExceptionMapper.java @@ -36,6 +36,7 @@ package sonia.scm.api.rest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; @@ -92,6 +93,7 @@ public class StatusExceptionMapper return Response.status(status) .entity(exception.getMessage()) + .type(MediaType.TEXT_PLAIN_TYPE) .build(); } } diff --git a/scm-webapp/src/main/java/sonia/scm/security/AccessTokenCookieIssuer.java b/scm-webapp/src/main/java/sonia/scm/security/DefaultAccessTokenCookieIssuer.java similarity index 93% rename from scm-webapp/src/main/java/sonia/scm/security/AccessTokenCookieIssuer.java rename to scm-webapp/src/main/java/sonia/scm/security/DefaultAccessTokenCookieIssuer.java index bb1473dca6..fd3f0e0d6f 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/AccessTokenCookieIssuer.java +++ b/scm-webapp/src/main/java/sonia/scm/security/DefaultAccessTokenCookieIssuer.java @@ -51,12 +51,12 @@ import java.util.concurrent.TimeUnit; * @author Sebastian Sdorra * @since 2.0.0 */ -public final class AccessTokenCookieIssuer { +public final class DefaultAccessTokenCookieIssuer implements AccessTokenCookieIssuer { /** - * the logger for AccessTokenCookieIssuer + * the logger for DefaultAccessTokenCookieIssuer */ - private static final Logger LOG = LoggerFactory.getLogger(AccessTokenCookieIssuer.class); + private static final Logger LOG = LoggerFactory.getLogger(DefaultAccessTokenCookieIssuer.class); private final ScmConfiguration configuration; @@ -66,7 +66,7 @@ public final class AccessTokenCookieIssuer { * @param configuration scm main configuration */ @Inject - public AccessTokenCookieIssuer(ScmConfiguration configuration) { + public DefaultAccessTokenCookieIssuer(ScmConfiguration configuration) { this.configuration = configuration; } diff --git a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java index 8fb5929188..4418cb40a8 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java +++ b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessToken.java @@ -87,6 +87,7 @@ public final class JwtAccessToken implements AccessToken { return ofNullable(claims.get(REFRESHABLE_UNTIL_CLAIM_KEY, Date.class)); } + @Override public Optional getParentKey() { return ofNullable(claims.get(PARENT_TOKEN_ID_CLAIM_KEY).toString()); } diff --git a/scm-webapp/src/main/java/sonia/scm/web/filter/HttpProtocolServletAuthenticationFilter.java b/scm-webapp/src/main/java/sonia/scm/web/filter/HttpProtocolServletAuthenticationFilter.java new file mode 100644 index 0000000000..77683bd6be --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/web/filter/HttpProtocolServletAuthenticationFilter.java @@ -0,0 +1,50 @@ +package sonia.scm.web.filter; + +import sonia.scm.Priority; +import sonia.scm.PushStateDispatcher; +import sonia.scm.config.ScmConfiguration; +import sonia.scm.filter.Filters; +import sonia.scm.filter.WebElement; +import sonia.scm.util.HttpUtil; +import sonia.scm.web.UserAgent; +import sonia.scm.web.UserAgentParser; +import sonia.scm.web.WebTokenGenerator; +import sonia.scm.web.protocol.HttpProtocolServlet; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Set; + +import static sonia.scm.util.HttpUtil.AUTHENTICATION_REALM; +import static sonia.scm.util.HttpUtil.HEADER_WWW_AUTHENTICATE; + +@Priority(Filters.PRIORITY_AUTHENTICATION) +@WebElement(value = HttpProtocolServlet.PATTERN) +public class HttpProtocolServletAuthenticationFilter extends AuthenticationFilter { + + private final PushStateDispatcher dispatcher; + private final UserAgentParser userAgentParser; + + @Inject + public HttpProtocolServletAuthenticationFilter( + ScmConfiguration configuration, + Set tokenGenerators, + PushStateDispatcher dispatcher, + UserAgentParser userAgentParser) { + super(configuration, tokenGenerators); + this.dispatcher = dispatcher; + this.userAgentParser = userAgentParser; + } + + @Override + protected void sendUnauthorizedError(HttpServletRequest request, HttpServletResponse response) throws IOException { + UserAgent userAgent = userAgentParser.parse(request); + if (userAgent.isBrowser()) { + dispatcher.dispatch(request, response, request.getRequestURI()); + } else { + HttpUtil.sendUnauthorized(request, response); + } + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java index 42428f9f77..1123dc94ce 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/AuthenticationResourceTest.java @@ -18,6 +18,7 @@ import sonia.scm.security.AccessToken; import sonia.scm.security.AccessTokenBuilder; import sonia.scm.security.AccessTokenBuilderFactory; import sonia.scm.security.AccessTokenCookieIssuer; +import sonia.scm.security.DefaultAccessTokenCookieIssuer; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -46,7 +47,7 @@ public class AuthenticationResourceTest { @Mock private AccessTokenBuilder accessTokenBuilder; - private AccessTokenCookieIssuer cookieIssuer = new AccessTokenCookieIssuer(mock(ScmConfiguration.class)); + private AccessTokenCookieIssuer cookieIssuer = new DefaultAccessTokenCookieIssuer(mock(ScmConfiguration.class)); private static final String AUTH_JSON_TRILLIAN = "{\n" + "\t\"cookie\": true,\n" + diff --git a/scm-webapp/src/test/java/sonia/scm/security/AccessTokenCookieIssuerTest.java b/scm-webapp/src/test/java/sonia/scm/security/DefaultAccessTokenCookieIssuerTest.java similarity index 93% rename from scm-webapp/src/test/java/sonia/scm/security/AccessTokenCookieIssuerTest.java rename to scm-webapp/src/test/java/sonia/scm/security/DefaultAccessTokenCookieIssuerTest.java index 03cf174226..9c80cfc67b 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/AccessTokenCookieIssuerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/DefaultAccessTokenCookieIssuerTest.java @@ -20,11 +20,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) -public class AccessTokenCookieIssuerTest { +public class DefaultAccessTokenCookieIssuerTest { private ScmConfiguration configuration; - private AccessTokenCookieIssuer issuer; + private DefaultAccessTokenCookieIssuer issuer; @Mock private HttpServletRequest request; @@ -41,7 +41,7 @@ public class AccessTokenCookieIssuerTest { @Before public void setUp() { configuration = new ScmConfiguration(); - issuer = new AccessTokenCookieIssuer(configuration); + issuer = new DefaultAccessTokenCookieIssuer(configuration); } @Test