SSO Oauth 2 - and other improvements. #1

Merged
niat8586 merged 1 commits from single-sign-on-oauth2 into main 2025-01-09 10:31:31 +01:00
22 changed files with 693 additions and 249 deletions
Showing only changes of commit e4e2f75f94 - Show all commits

View File

@ -10,5 +10,18 @@ services:
- '3306:3306'
volumes:
- mariadb_data:/var/lib/mysql
oauth2:
build:
context: https://github.com/dsv-su/toker.git
dockerfile: embedded.Dockerfile
ports:
- '51337:8080'
environment:
- CLIENT_ID=seshat
- CLIENT_SECRET=n0tS3cr3t
- CLIENT_REDIRECT_URI=http://localhost:8181/login/oauth2/code/seshat
volumes:
mariadb_data:

View File

@ -39,6 +39,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>

View File

@ -6,24 +6,32 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
import org.springframework.web.filter.ForwardedHeaderFilter;
import se.su.dsv.seshat.services.CustomOAuth2loginSuccessHandler;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
public SecurityFilterChain securityFilterChain(
HttpSecurity httpSecurity,
CustomOAuth2loginSuccessHandler customOAuth2loginSuccessHandler
) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new ForwardedHeaderFilter(), WebAsyncManagerIntegrationFilter.class)
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/css/**", "/js/**", "/register", "/login").permitAll()
.anyRequest().authenticated()
)
.formLogin(login -> login
.loginPage("/login")
.defaultSuccessUrl("/files/manage", true)
.permitAll()
.oauth2Login(oauth2 -> oauth2
.successHandler(customOAuth2loginSuccessHandler)
)
.logout(logout -> logout
.logoutSuccessUrl("/login?logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.clearAuthentication(true)
.deleteCookies("JSESSIONID", "auth_code", "refresh_token", "Authorization")
.permitAll()
);
return httpSecurity.build();
@ -33,4 +41,5 @@ public class SecurityConfig {
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -24,6 +24,8 @@ import se.su.dsv.seshat.services.UserService;
import java.io.File;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Controller
@ -50,7 +52,19 @@ public class FileController {
.filter(file -> file.getJobStatus() != null)
.toList();
model.addAttribute("files", files);
// Map<String, List<FileMetadata>> filesByDirectory = files.stream().collect(Collectors.groupingBy(FileMetadata::getOutputDirectory));
Map<FileMetadata, List<FileMetadata>> filesByDirectory = files.stream()
.collect(Collectors.groupingBy(outputFile -> {
return uploaded.stream()
.filter(uploadedFile -> uploadedFile.getOutputDirectory().equals(outputFile.getOutputDirectory()))
.filter(uploadedFile -> outputFile.getSourceFile().equals(uploadedFile.getFilePath()))
.findFirst()
.orElseThrow(/* Will never happen */);
}));
model.addAttribute("filesByDirectory", filesByDirectory);
model.addAttribute("statuses", statuses);
return "file-management";
@ -79,7 +93,6 @@ public class FileController {
return "redirect:/files/manage";
}
// Browsers do not support DELETE method so for individual file deletion we use GET
@GetMapping("files/download/{id}")
public ResponseEntity<Resource> downloadFile(@PathVariable("id") Long id) {
try {
@ -116,7 +129,7 @@ public class FileController {
}
// Browsers do not support DELETE method so for individual file deletion we use GET
@GetMapping("/files/delete/{id}")
public String deleteFile(@PathVariable("id") Long id, Authentication authentication, Model model) {
try {

View File

@ -0,0 +1,18 @@
package se.su.dsv.seshat.controllers;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LandingController {
@GetMapping("/")
public String showHomePage(Authentication authentication) {
if (authentication != null) {
return "redirect:/files/manage";
}
return "redirect:/login";
}
}

View File

@ -1,33 +0,0 @@
package se.su.dsv.seshat.controllers;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class LoginController {
@GetMapping("/")
public String showHomePage(Authentication authentication) {
if (authentication != null) {
return "redirect:/files/manage";
}
return "redirect:/login";
}
@GetMapping("/login")
public String showLoginPage(Model model, String error, String logout) {
if (error != null) {
model.addAttribute("error", "Invalid username or password");
}
if (logout != null) {
model.addAttribute("message", "Logged out successfully");
}
return "login";
}
}

View File

@ -1,37 +0,0 @@
package se.su.dsv.seshat.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import se.su.dsv.seshat.services.UserService;
@Controller
public class RegistrationController {
private final UserService userService;
public RegistrationController(UserService userService) {
this.userService = userService;
}
@GetMapping("/register")
public String showRegistrationForm() {
return "register";
}
@PostMapping("/register")
public String registerUser(@RequestParam String username,
@RequestParam String email,
@RequestParam String password,
Model model) {
try{
userService.registerUser(username, email, password);
return "redirect:/login";
} catch (IllegalArgumentException e) {
model.addAttribute("error", "Registration failed: " + e.getMessage());
return "register";
}
}
}

View File

@ -25,9 +25,6 @@ public class AppUser {
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
@Column(nullable = false, unique = true)
private String email;
@ -42,9 +39,8 @@ public class AppUser {
public AppUser() {}
public AppUser(String username, String password, String email, String roles) {
public AppUser(String username, String email, String roles) {
this.username = username;
this.password = password;
this.email = email;
this.roles = roles;
}
@ -65,14 +61,6 @@ public class AppUser {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
@ -111,14 +99,13 @@ public class AppUser {
if (!(o instanceof AppUser appUser)) return false;
return Objects.equals(id, appUser.id)
&& Objects.equals(username, appUser.username)
&& Objects.equals(password, appUser.password)
&& Objects.equals(email, appUser.email)
&& Objects.equals(roles, appUser.roles);
}
@Override
public int hashCode() {
return Objects.hash(id, username, password, email, roles);
return Objects.hash(id, username, email, roles);
}
@Override
@ -126,7 +113,6 @@ public class AppUser {
return "AppUser{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", roles='" + roles + '\'' +
", createdAt=" + createdAt +

View File

@ -15,7 +15,7 @@ public class DeletedFile {
@GeneratedValue
private Long id;
@Column(nullable = false)
@Column(nullable = false, length = 1000)
private String filePath;
@Column(nullable = false)

View File

@ -23,12 +23,15 @@ public class FileMetadata {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
@Column(nullable = false, length = 512)
private String fileName;
@Column(nullable = false)
@Column(nullable = false, length = 1000)
private String filePath;
@Column(length = 1000)
private String sourceFile;
private String language;
@ManyToOne(fetch = FetchType.EAGER)
@ -36,13 +39,13 @@ public class FileMetadata {
private AppUser user;
@Column(nullable = false)
private LocalDateTime uploadedAt = LocalDateTime.now();
private LocalDateTime uploadedAt;
@Enumerated(EnumType.STRING)
@Column(name ="job_status", nullable = false, length = 20)
@Column(name ="job_status", length = 20)
private JobStatus jobStatus = JobStatus.PENDING;
@Column
@Column(length = 1000)
private String outputDirectory;
public FileMetadata() {}
@ -76,6 +79,14 @@ public class FileMetadata {
this.filePath = filePath;
}
public String getSourceFile() {
return sourceFile;
}
public void setSourceFile(String sourceFile) {
this.sourceFile = sourceFile;
}
public String getLanguage() {
return language;
}
@ -116,6 +127,8 @@ public class FileMetadata {
this.outputDirectory = outputDirectory;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@ -0,0 +1,43 @@
package se.su.dsv.seshat.services;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service
public class CustomOAuth2loginSuccessHandler implements AuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(CustomOAuth2loginSuccessHandler.class);
private final String redirectUrl;
private final UserService userService;
public CustomOAuth2loginSuccessHandler(@Value("${app.onSuccess-homepage}") String redirectUrl, UserService userService) {
this.redirectUrl = redirectUrl;
this.userService = userService;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
logger.info("OAuth2 attributes: {}", oAuth2User.getAttributes());
String username = oAuth2User.getName();
// If the user does not have an email, set it to "no-email". We will not send any eamil notifications to this user.
String email = oAuth2User.getAttribute("mail") != null ? oAuth2User.getAttribute("mail") : "no-email";
if(!userService.existsByUsername(oAuth2User.getAttribute("principal"))) {
userService.registerUser(username, email);
}
response.sendRedirect(redirectUrl);
}
}

View File

@ -23,7 +23,6 @@ public class CustomUserDetailService implements UserDetailsService {
.orElseThrow(() -> new UsernameNotFoundException("User not found: " + username));
return User.builder()
.username(appUser.getUsername())
.password(appUser.getPassword())
.roles(appUser.getRoles().split(","))
.build();
}

View File

@ -3,7 +3,8 @@ package se.su.dsv.seshat.services;
import jakarta.annotation.PostConstruct;
import jakarta.persistence.EntityNotFoundException;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
import se.su.dsv.seshat.entities.DeletedFile;
@ -15,10 +16,9 @@ import se.su.dsv.seshat.repositories.FileMetadataRepository;
import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Service
public class JobProcessorService {
@ -31,9 +31,6 @@ public class JobProcessorService {
private final StorageService storageService;
private final DeletedFileRepository deletedFileRepository;
@Value("${app.output-root}")
private String outputRoot;
public JobProcessorService(FileMetadataRepository fileMetadataRepository,
Transcriber transcriber,
StorageService storageService,
@ -88,9 +85,11 @@ public class JobProcessorService {
if (transcribe) {
logger.info("Transcription successful for file: {}", managedJob.getFileName());
storageService.addTranscribedFilesToDatabase(managedJob.getUser(), managedJob.getOutputDirectory());
managedJob.setJobStatus(JobStatus.COMPLETED);
fileMetadataRepository.saveAndFlush(managedJob);
//TODO: This method can just take the filemetadata object managedJob as arugument we will need further information from it.
storageService.addTranscribedFilesToDatabase(managedJob);
cleanupFile(managedJob);
fileMetadataRepository.delete(managedJob); // Delete the job after successful transcription
break;
} else {
logger.info("Transcription failed for file: {}", managedJob.getFileName());
@ -111,20 +110,22 @@ public class JobProcessorService {
}
private boolean cleanupFile(FileMetadata jobFile) {
private void cleanupFile(FileMetadata jobFile) {
String filePath = jobFile.getFilePath();
File file = new File(filePath);
File parentDir = file.getParentFile();
if(file.exists()) {
if(file.delete()) {
recordFileDeletion(filePath, "JobProcessorService");
// Delete the parent directory if it is empty
if(parentDir != null && parentDir.isDirectory() && Objects.requireNonNull(parentDir.list()).length == 0) {
parentDir.delete();
}
logger.info("File deleted successfully: {}", filePath);
return true;
} else {
logger.error("Failed to delete file: {}", filePath);
return false;
}
}
return false;
}
private void recordFileDeletion(String filePath, String jobProcessorService) {

View File

@ -1,6 +1,8 @@
package se.su.dsv.seshat.services;
import jakarta.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@ -18,7 +20,10 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@ -26,6 +31,8 @@ import java.util.zip.ZipOutputStream;
@Service
public class StorageService {
private final static Logger logger = LoggerFactory.getLogger(StorageService.class);
private final DeletedFileRepository deletedFileRepository;
@Value("${app.upload-root}")
private String uploadRoot;
@ -41,7 +48,9 @@ public class StorageService {
}
@Transactional
public void addTranscribedFilesToDatabase(AppUser user, String outputDirectory) {
public void addTranscribedFilesToDatabase(FileMetadata sourceFile) {
String outputDirectory = sourceFile.getOutputDirectory();
AppUser user = sourceFile.getUser();
File userOutputDirectory = new File(outputDirectory);
if(!userOutputDirectory.exists() || !userOutputDirectory.isDirectory()) {
return;
@ -64,6 +73,9 @@ public class StorageService {
fileMetadata.setFilePath(filePath);
fileMetadata.setUser(user);
fileMetadata.setJobStatus(null);
fileMetadata.setUploadedAt(sourceFile.getUploadedAt());
fileMetadata.setOutputDirectory(sourceFile.getOutputDirectory());
fileMetadata.setSourceFile(sourceFile.getFilePath());
fileMetadataRepository.save(fileMetadata);
}
}
@ -84,7 +96,7 @@ public class StorageService {
String sanitizedFilename = sanitizeFilename(originalFilename);
// Users upload directory
Path userUploadDir = Paths.get(uploadRoot, user.getUsername());
Path userUploadDir = Paths.get(uploadRoot, user.getUsername(), UUID.randomUUID().toString());
try {
if(!Files.exists(userUploadDir)) {
@ -107,7 +119,9 @@ public class StorageService {
} else {
metadata.setLanguage("auto");
}
metadata.setOutputDirectory(outputRoot + File.separator + user.getUsername());
metadata.setUploadedAt(LocalDateTime.now());
String fileFolder = fileNameAndUploadedTime(metadata);
metadata.setOutputDirectory(outputRoot + File.separator + user.getUsername() + File.separator + fileFolder);
metadata.setUser(user);
return fileMetadataRepository.save(metadata);
} catch (IOException e) {
@ -126,6 +140,7 @@ public class StorageService {
return fileMetadataRepository.findByUserId(user.getId())
.stream()
.filter(file -> file.getFilePath().startsWith(uploadRoot))
.sorted((file1, file2) -> file2.getUploadedAt().compareTo(file1.getUploadedAt()))
.collect(Collectors.toList());
}
@ -147,9 +162,21 @@ public class StorageService {
deletedFile.setDeletionTime(LocalDateTime.now());
deletedFileRepository.save(deletedFile);
fileMetadataRepository.delete(fileMetadata);
// Delete the directory if it is empty
Path outputDirectory = Paths.get(fileMetadata.getOutputDirectory());
if (Files.exists(outputDirectory) && Files.isDirectory(outputDirectory)) {
File[] files = outputDirectory.toFile().listFiles();
if (files != null && files.length == 0) {
Files.delete(outputDirectory);
}
}
return true;
} catch (IllegalArgumentException e) {
return false;
} catch (IOException e) {
logger.info("Failed to delete file or directory: " + e.getMessage());
}
} else {
return false;
@ -166,6 +193,9 @@ public class StorageService {
}
public File createZipFromFiles(List<Long> fileIds, AppUser user) throws IOException {
// TODO: Use java.nio FileSystems.newFileSystem(Files.createTempFile("selected_files", ".zip"));
// FileSystems.newFileSystem(Files.createTempFile("selected_files", ".zip"));
// Temporary ZIP file
File zipFile = File.createTempFile("selected_files", ".zip");
@ -183,9 +213,9 @@ public class StorageService {
File file = new File(fileMetadata.getFilePath());
if (file.exists()) {
Path filePath = file.toPath();
String closestParentDir = filePath.getName(filePath.getNameCount() - 2).toString();
// Add new entry for the file in the ZIP
zos.putNextEntry(new ZipEntry(file.getName()));
zos.putNextEntry(new ZipEntry(closestParentDir + File.separator + file.getName()));
// Copy file contents to the ZIP
Files.copy(filePath, zos);
@ -200,4 +230,19 @@ public class StorageService {
private String sanitizeFilename(String filename) {
return filename.replaceAll("[^a-zA-Z0-9.-]", "_");
}
private String fileNameAndUploadedTime(FileMetadata file) {
String fileName = file.getFileName();
LocalDateTime uploadedAt = file.getUploadedAt();
String uploadedToSeconds = uploadedAt.truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
return fileNameWithoutExtension(file.getFileName()) + "_" + uploadedToSeconds.replaceAll(":|-", "");
}
private String fileNameWithoutExtension(String fileName) {
int lastDotIndex = fileName.lastIndexOf('.');
if (lastDotIndex != -1) {
return fileName.substring(0, lastDotIndex);
}
return fileName;
}
}

View File

@ -1,11 +1,11 @@
package se.su.dsv.seshat.services;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Service
public class Transcriber {

View File

@ -1,6 +1,5 @@
package se.su.dsv.seshat.services;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import se.su.dsv.seshat.entities.AppUser;
import se.su.dsv.seshat.repositories.AppUserRepository;
@ -9,14 +8,12 @@ import se.su.dsv.seshat.repositories.AppUserRepository;
public class UserService {
private final AppUserRepository appUserRepository;
private final PasswordEncoder passwordEncoder;
public UserService(AppUserRepository appUserRepository, PasswordEncoder passwordEncoder) {
public UserService(AppUserRepository appUserRepository) {
this.appUserRepository = appUserRepository;
this.passwordEncoder = passwordEncoder;
}
public void registerUser(String username, String email,String password) {
public void registerUser(String username, String email) {
if (appUserRepository.existsByUsername(username)) {
throw new IllegalArgumentException("Username already exists");
}
@ -24,7 +21,7 @@ public class UserService {
throw new IllegalArgumentException("Email already exists");
}
AppUser newUser = new AppUser(username, passwordEncoder.encode(password), email, "USER");
AppUser newUser = new AppUser(username, email, "USER");
appUserRepository.save(newUser);
}
@ -32,4 +29,8 @@ public class UserService {
return appUserRepository.findByUsername(username)
.orElseThrow(() -> new IllegalArgumentException("User not found"));
}
public boolean existsByUsername(String username) {
return appUserRepository.existsByUsername(username);
}
}

View File

@ -6,7 +6,7 @@ spring.servlet.multipart.max-request-size=5GB
app.upload-root=/seshat/uploads
app.output-root=/seshat/outputs
app.api-url=http://localhost:8181/seshat/api
app.onSuccess-homepage=/files/manage
# Database properties (local development)
spring.datasource.url=jdbc:mariadb://localhost:3306/seshat
@ -17,3 +17,14 @@ spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
# JPA properties
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
# OAuth2 properties, remember if you change the registration.provider the provider properties must be updated
spring.security.oauth2.client.provider.docker.authorization-uri=http://localhost:51337/authorize
spring.security.oauth2.client.provider.docker.token-uri=http://localhost:51337/exchange
spring.security.oauth2.client.provider.docker.user-info-uri=http://localhost:51337/verify
spring.security.oauth2.client.provider.docker.user-name-attribute=sub
spring.security.oauth2.client.registration.seshat.client-id=seshat
spring.security.oauth2.client.registration.seshat.client-secret=n0tS3cr3t
spring.security.oauth2.client.registration.seshat.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.seshat.provider=docker
spring.security.oauth2.client.registration.seshat.redirect-uri={baseUrl}/login/oauth2/code/{registrationId}

View File

@ -1,3 +1,7 @@
:root {
--bs-primary-rgb: 0, 47, 95;
--bs-btn-bg: #002F5F;
}
/* Sticky footer layout */
/* Header Styling */
.header {
@ -7,8 +11,9 @@
}
.header .app-title {
font-size: 1.5rem;
font-weight: bold;
font-family: 'PMN Caecilia', serif;
font-size: 2rem;
font-weight: normal;
margin: 0;
}
@ -23,8 +28,27 @@
font-size: 1.5rem;
}
.logo {
width: 12rem;
margin-right: 1rem;
}
.table-wrapper {
max-height: 160px;
}
.table thead th {
position: sticky;
top: 0;
z-index: 1;
background-color: #f9fafb;
}
footer {
margin-top: 1rem;
}
html, body {
height: 100%; /* Ensure the height of the body is at least the viewport height */
min-height: 100dvh;
}
body {

View File

@ -0,0 +1,379 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Logotyper" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 671.54 283.1" style="enable-background:new 0 0 671.54 283.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g>
<g id="Group_33" transform="translate(-337.004 -221)">
<g id="Group_27" transform="translate(143.967)">
<path id="Path_1187" class="st0" d="M388.85,289.02c0.14,0.16,0.07,0.27-0.08,0.4c-0.27,0.22-1.77,2.43-1.95,2.7
c-0.11,0.18-0.13-0.14-0.07-0.32c0.51-1.48,0.08-3.13-1.08-4.18c-1.21-0.92-2.93-0.68-3.84,0.53c-0.01,0.02-0.03,0.04-0.04,0.06
c-0.94,1.4-0.97,2.67,0,6.33c1.01,3.81,0.59,5.21-0.8,6.83c-1.87,1.85-4.82,2.05-6.92,0.47c-2.71-1.89-2.82-2.32-3.24-2.49
c-0.33-0.14-0.32-0.4,0-0.8c0.48-0.57,2.09-2.75,2.36-3.16c0.18-0.28,0.22,0.04,0.03,0.45c-0.84,1.64-0.4,3.64,1.05,4.77
c1.18,1.1,3.03,1.03,4.13-0.15c0.06-0.07,0.12-0.14,0.18-0.21c0.8-0.96,1.27-1.89,0.14-6.26c-1.2-4.61-0.37-6.12,1.37-7.48
c1.79-1.46,4.37-1.44,6.14,0.04c0.7,0.55,1.35,1.14,1.97,1.78c0.22,0.22,0.34,0.46,0.46,0.57S388.78,288.93,388.85,289.02z"/>
<path id="Path_1188" class="st0" d="M244.24,341.13c0.06-0.16,0.24-0.08,0.47,0c0.95,0.26,1.92,0.43,2.9,0.51
c0.49,0-0.34,0.37-0.59,0.4c-0.69,0.09-2.05,0.49-2.67,2.77c-0.42,1.3,0.29,2.69,1.59,3.11c0.07,0.02,0.13,0.04,0.2,0.06
c2,0.4,3.06-0.36,5.99-2.72c1.78-1.92,4.44-2.75,6.99-2.19c2.41,0.86,3.79,3.4,3.2,5.89c-0.27,1.31-0.79,2.56-1.54,3.68
c-0.12,0.34-0.28,0.46-0.78,0.32c-0.64-0.18-3.05-0.53-3.48-0.58c-0.78-0.09-0.45-0.4,0-0.44c1.24-0.16,3.94-0.5,4.48-3.15
c0.36-1.38-0.47-2.78-1.84-3.14c-0.08-0.02-0.17-0.04-0.25-0.05c-1.23-0.3-2.57-0.26-6.03,2.61c-3.73,3.09-5.32,3.08-7.33,2.17
c-2.1-0.92-3.19-3.26-2.55-5.47c0.21-1.14,0.59-2.24,1.13-3.26C244.24,341.52,244.2,341.24,244.24,341.13z"/>
<path id="Path_1189" class="st0" d="M358.57,449.92c-0.26,0-0.21-0.22-0.25-0.4c0,0-0.66-2.19-0.72-2.37
c-0.06-0.17,0.13-0.24,0.26-0.08c0.95,1.05,2.39,1.51,3.77,1.2c1.48-0.35,2.41-1.82,2.09-3.31c-0.52-1.6-2.09-2.35-5.53-3.93
c-3.1-1.43-4.1-2.86-4.4-4.64c-0.26-2.68,1.41-5.17,4-5.95c2.59-0.8,3.2-0.72,3.72-0.98c0.4-0.21,0.45,0.61,0.5,0.76
c0.25,0.69,0.92,2.84,1.08,3.24c0.16,0.4-0.14,0.51-0.33,0.1c-0.89-1.57-2.69-2.38-4.45-2c-2.31,0.75-2.65,2.4-2.33,3.49
c0.36,1.2,0.57,2.17,4.92,4c4.23,1.78,5.06,3.6,5.08,5.65c-0.14,2.34-1.88,4.28-4.2,4.66c-0.68,0.18-1.38,0.28-2.09,0.31
c-0.31,0.05-0.55,0.07-0.71,0.09C358.82,449.78,358.78,449.92,358.57,449.92z"/>
<path id="Path_1190" class="st0" d="M390.91,293.8c0.62-0.27,1.21-0.61,1.74-1.03c0.22-0.18,0.64,0,0.9,0.26
c0.17,0.17,3.95,3.91,4.69,4.71c1.01,1.07,4.36,4.15,4.79,4.57c0.43,0.42,0.84,0.64,0.4,0.93c-0.44,0.28-1.36,0.8-1.64,0.95
c-0.28,0.15-0.19,0.03-0.19-0.28c0-0.32-0.22-0.8-1.16-1.77c-0.94-0.97-2.02-2.1-2.22-2.26c-0.2-0.16-0.27-0.19-0.44-0.04
c-0.27,0.24-3.97,4-4.79,4.86c-2.07,1.94-3.99,4.04-5.74,6.27c-0.15,0.77,0.1,0.93,0.2,1.07c0.1,0.14,0.22,0.77-0.02,0.53
c-0.24-0.24-1.79-1.93-2.15-2.27c-0.36-0.34-1.87-1.6-2.09-1.81s-0.06-0.32,0.31-0.17c0.51,0.29,1.13,0.3,1.65,0.03
c2.07-1.66,4.02-3.48,5.83-5.42c0.59-0.59,4.6-4.77,4.71-4.89c0.18-0.2,0.25-0.3,0-0.62c-1.02-1.07-2.11-2.08-3.25-3.02
c-0.32-0.26-0.72-0.41-1.13-0.43C390.98,293.97,390.56,293.96,390.91,293.8z"/>
<path id="Path_1191" class="st0" d="M253.1,323.87c-0.35-0.4-1.2-1.11-1.67-1.51c-0.22-0.18-0.1-0.42,0.1-0.74
c0.12-0.2,2.77-5.07,3.38-5.99c0.8-1.24,3.2-5.23,3.49-5.75c0.3-0.52,0.52-0.91,0.77-0.68c0.43,0.43,0.83,0.9,1.2,1.39
c0.21,0.3,0.09,0.15-0.22,0.15s-0.72,0.63-1.45,1.77c-0.52,0.83-0.99,1.68-1.41,2.56c-0.15,0.32,0.06,0.4,0.24,0.54
c0.31,0.2,4.69,2.91,5.73,3.52c2.4,1.48,4.93,2.75,7.54,3.8c0.8-0.04,0.78-0.17,0.92-0.27c0.22-0.16,0.67-0.23,0.45,0
c-0.58,0.75-1.1,1.53-1.57,2.35c-0.37,0.66-1.22,2.24-1.33,2.49s-0.12-0.16-0.1-0.5c0.02-0.4,0.27-0.77-0.33-1.26
c-1.06-0.87-6.1-3.82-6.79-4.25c-0.69-0.43-5.63-3.22-5.99-3.34c-0.26-0.09-0.47-0.4-0.67-0.03c-0.88,1.36-1.63,2.8-2.23,4.31
c-0.09,0.33-0.09,0.69-0.02,1.02C253.25,323.89,253.27,324.05,253.1,323.87z"/>
<path id="Path_1192" class="st0" d="M275.67,294.27c-0.24-0.67-0.56-1.31-0.94-1.91c-0.16-0.32-0.17-0.31,0.26-0.66
c0.19-0.15,4.6-3.41,5.47-4.08c1.2-0.92,5.25-3.65,5.73-4c0.48-0.35,1.02-0.56,1.2-0.12c0.18,0.44,0.66,1.63,0.75,1.93
c0.12,0.44-0.06,0.11-0.38-0.16c-0.24-0.22-0.68-0.18-1.81,0.58c-1.13,0.76-2.71,1.8-2.92,2s-0.18,0.2-0.08,0.4
c0.25,0.5,3.16,4.77,3.98,5.85c1.65,2.43,3.48,4.74,5.46,6.91c0.3,0.15,0.65,0.16,0.96,0.04c0.24-0.05,0.53,0.03,0.13,0.26
c-0.4,0.23-1.6,1.04-2.04,1.33c-0.44,0.29-1.57,1.16-1.96,1.51c-0.47,0.4-0.34-0.03-0.13-0.31c0.21-0.28,0.36-0.46,0.06-1.16
c-1.28-2.28-2.7-4.49-4.25-6.6c-0.48-0.68-4.31-5.8-4.56-6.13c-0.14-0.18-0.18-0.24-0.52,0s-3.32,2.51-3.76,2.92
c-0.34,0.33-0.52,0.4-0.56,0.84C275.74,293.96,275.75,294.6,275.67,294.27z"/>
<path id="Path_1193" class="st0" d="M410.65,311.56c3.75,3.82,3.69,9.95-0.13,13.7c-0.18,0.18-0.38,0.36-0.58,0.52
c-3.91,3.33-9.72,3.13-13.38-0.47c-3.67-3.9-3.49-10.03,0.4-13.7c3.66-3.79,9.7-3.9,13.5-0.24
C410.52,311.44,410.59,311.5,410.65,311.56z M399.28,313.9c-3.31,2.4-4.04,7.03-1.63,10.34c0.05,0.07,0.1,0.13,0.15,0.2
c3.26,2.47,7.91,1.89,10.46-1.32c3.34-2.57,3.97-7.35,1.4-10.69c-0.1-0.13-0.2-0.26-0.31-0.38
C407.5,310.43,403.39,309.9,399.28,313.9L399.28,313.9z"/>
<path id="Path_1194" class="st0" d="M416.12,403.32c-1.72,4.99-7.17,7.65-12.16,5.92c-0.34-0.12-0.67-0.25-0.99-0.41
c-4.51-2.07-6.79-7.17-5.31-11.91c1.8-4.95,7.26-7.52,12.23-5.75C414.94,392.85,417.72,398.25,416.12,403.32z M408.98,394.02
c-3.48-1.91-7.85-0.64-9.77,2.84c-0.08,0.14-0.15,0.29-0.22,0.44c-0.86,2.53,0.14,6.33,5.74,8.43c5.43,2.03,9.51,0,10.44-3.64
C415.52,400.73,415.6,396.39,408.98,394.02z"/>
<path id="Path_1195" class="st0" d="M409.07,347.58c-0.82-0.03-1.64-0.12-2.45-0.26c-0.56-0.12-0.64-0.13-0.8-0.36
c-1.62-2.1-2.51-4.68-2.51-7.34c-0.37-4.49,2.45-8.63,6.76-9.95c3.84-1.05,7.94,0.33,10.36,3.5c1.34,1.9,2.1,4.15,2.17,6.47
c0.09,1.37,0.21,2.19,0.27,2.63c0.12,0.74,0.11,0.94,0.27,1.14c0.16,0.2-0.07,0.4-0.35,0.4s-1.36,0.18-1.91,0.31
c-0.4,0.1-1.25,0.33-1.36,0.36c-0.59,0.14-0.57,0-0.11-0.36c1-0.52,1.69-1.48,1.88-2.59c0.49-2.57-0.22-5.22-1.94-7.19
c-2.32-2.4-5.94-3-8.92-1.49c-3.3,1.24-5.52,4.36-5.59,7.89c-0.18,2.79,1.47,5.38,4.08,6.39
C409.54,347.37,409.9,347.56,409.07,347.58z"/>
<path id="Path_1196" class="st0" d="M424.46,349.87c0,0.72,0.33,3.97,0.46,4.6c0.16,0.76-0.18,0.4-0.22,0.14
c-0.12-0.42-0.48-0.72-0.91-0.76c-2.65,0.03-5.3,0.23-7.92,0.59c2.18,1.95,4.47,3.76,6.88,5.43c0.54,0.45,1.15,0.8,1.8,1.04
c0.17,0,0.08,0.13,0.16-0.09c0.1-0.3,0.4-1.27,0.36,0.2c0,0.35-0.03,1.41,0,1.68c0.03,0.27,0.13,1.01,0.15,1.17
c0.11,0.8-0.02,0.63-0.61-0.09c-1.04-1.08-2.18-2.04-3.42-2.88c-0.65-0.47-4.77-3.6-4.77-3.6s-5.92,5.62-7.04,6.85
c-0.88,0.88-1.65,1.86-2.31,2.92c-0.19,0.43-0.35,0.64-0.28,0.23c0.05-0.26,0.23-1.88,0.27-2.59c0.04-0.62,0.1-2.54,0.11-2.73
c0.02-0.4,0.18-0.1,0.4-0.04c1.42-0.9,2.7-2.01,3.81-3.28c1.39-1.37,3.7-3.88,3.88-4.12c-1.93,0.13-3.85,0.36-5.75,0.68
c-0.73,0.09-1.43,0.34-2.05,0.74c-0.22,0.2-0.36,0.46-0.4,0.76c-0.03,0.24-0.26,0.35-0.3,0.04c-0.04-0.32-0.11-2-0.15-2.6
c-0.04-0.6-0.24-2-0.28-2.2c-0.04-0.2,0.16-0.36,0.28-0.08c0.08,0.27,0.29,0.47,0.55,0.55c0.66,0.26,1.55,0.27,8.08-0.5
c2.59-0.18,5.17-0.55,7.7-1.11c0.69-0.18,1.12-0.44,1.2-1.02C424.18,349.47,424.48,348.81,424.46,349.87z"/>
<path id="Path_1197" class="st0" d="M424.58,372.31c-0.13,0.59-0.66,3.81-0.66,4.46c0,0.65-0.3,0.66-0.38,0.22
c-0.02-0.38-0.26-0.72-0.61-0.87c-1.04-0.43-2.13-0.7-3.25-0.8c-2.26-0.36-3.74-0.62-3.74-0.62s-0.7,2.98-1.09,4.79
c-0.49,2.27-1.03,5.27-1.03,5.27l4.36,1.23c1.17,0.32,2.96,1.06,3.53,0.1c0.4-0.68,0.65-0.53,0.27,0.2
c-0.13,0.26-0.93,3.35-1.05,3.97c-0.24,1.15-0.4,0.42-0.34,0.15c0.06-0.27,0.27-0.74-0.74-1.14c-1.01-0.4-4.42-1.55-7.43-2.4
c-2.52-0.9-5.14-1.51-7.8-1.84c-0.68,0.06-0.86,0.21-1.02,0.44c-0.23,0.32-0.63,0.42-0.31-0.11c0.53-1.34,0.93-2.72,1.2-4.13
c0.2-1.34,0.4-0.4,0.38-0.15c-0.04,0.44,0.21,0.86,0.62,1.03c2.25,0.91,4.56,1.66,6.91,2.25c0,0,0.7-2.75,1.16-4.87
c0.55-2.5,0.92-4.97,0.92-4.97s-1.38-0.22-2.36-0.4c-1.68-0.31-3.38-0.5-5.09-0.55c-0.35,0.1-0.64,0.35-0.78,0.69
c-0.07,0.23-0.52,0.66-0.27-0.16c0.3-1.35,0.5-2.71,0.59-4.09c0.06-1.15,0.36-0.65,0.37-0.32c0.05,0.33,0.24,0.62,0.52,0.8
c2.54,0.75,5.14,1.25,7.78,1.49c2.75,0.55,5.54,0.85,8.33,0.9c0.64-0.22,0.6-0.46,0.72-0.73
C424.41,371.88,424.76,371.47,424.58,372.31z"/>
<path id="Path_1198" class="st0" d="M406.64,417.68c-1.1,1.09-2.11,2.27-3.02,3.51c-0.47,0.64-0.4,0.13-0.28-0.12
c0.23-0.46,0.09-0.61-0.09-1.01c-1.66-1.83-3.5-3.48-5.48-4.95c-1.87-1.83-3.98-3.4-6.28-4.67c-0.4,0-0.73-0.05-1.54,0.69
c-1.12,1.04-2.12,2.21-2.98,3.47c-0.3,0.57-0.43,1.22-0.37,1.87c0,0.44-0.13,0.4-0.28,0c-0.26-0.8-0.46-1.62-0.61-2.45
c-0.03-0.25,0.07-0.49,0.26-0.65c0.45-0.49,4.28-4.83,4.84-5.45c0.64-0.69,1.23-1.42,1.78-2.19c0.36-0.62,0.48-0.18,0.37,0.14
c-0.23,0.38-0.29,0.84-0.18,1.27c1.76,2.1,3.81,3.94,6.08,5.48c2.02,1.96,4.29,3.65,6.74,5.02c0.33,0.05,0.66-0.06,0.9-0.28
C406.68,417.2,407.16,417.32,406.64,417.68z"/>
<path id="Path_1199" class="st0" d="M383.18,417.49c0.2,0.5,2.15,3.85,4.18,7.26c2.11,3.52,4.4,7.19,4.7,7.75
c0.62,1.08,0.64,1.34-0.43,0.8c-1.55-0.77-7.76-3.9-8.79-4.4c-1.03-0.5-6.11-3.08-6.11-3.08s1.1,8.29,1.2,8.75
c0.1,0.47,0.98,7.37,1.03,7.72c0.05,0.35,0.05,0.9-0.58,0.31c-0.62-0.59-10.43-13.1-10.92-13.67c-0.35-0.45-0.87-0.75-1.43-0.84
c-0.26-0.05-0.52-0.04-0.77,0.04c-0.25,0.09-0.44-0.14-0.08-0.28c0.44-0.17,3.94-1.97,4.28-2.19c0.22-0.13,0.52,0.04,0.18,0.25
c-0.44,0.27-0.5,0.46-0.4,0.86c0.22,0.95,7.32,9.77,7.32,9.77s-1.2-7.92-1.41-8.93c-0.21-1.01-0.9-5.68-0.9-5.68s0-0.3,0.3-0.14
c0.3,0.16,7.24,3.7,7.99,4.06s5.19,2.56,5.19,2.56s-3.9-6.33-5.51-8.85c-0.23-0.44-0.6-0.78-1.05-0.97
c-0.55-0.11-0.72,0.12-1.04,0.26c-0.16,0.07-0.4-0.13,0.07-0.4c0.57-0.35,1.11-0.74,1.62-1.17c0.4-0.31,1.4-1.27,1.56-1.43
c0.16-0.16,0.4,0.04,0.23,0.21C383.12,416.36,382.93,416.98,383.18,417.49z"/>
<path id="Path_1200" class="st0" d="M340.34,441.57c-0.04,0.33,0.06,4.16,0.1,4.64c0,0.22-0.18,0.16-0.31-0.33
c-0.12-0.38-0.42-0.67-0.8-0.78c-1.42-0.18-2.86-0.21-4.3-0.08c-0.09,1.66,0.04,3.32,0.38,4.95c0.44,0.48,0.51,0.43,0.7,0.47
c0.2,0.04,0.67,0.29,0.36,0.26c-0.6-0.06-3.94-0.06-4.69,0.02c-0.55,0.06-0.27-0.2,0.19-0.3c0.46-0.1,0.7-0.36,0.87-0.94
c0.13-1.49,0.16-2.99,0.09-4.49c-1.53-0.05-3.07,0.03-4.59,0.24c-0.33,0.19-0.54,0.54-0.55,0.92c-0.04,0.32-0.38,0.6-0.33,0.17
c0.1-1.38,0.11-2.76,0.04-4.14c-0.08-0.55,0.05-0.47,0.23-0.14c0.22,0.4,0.15,0.63,0.62,0.82c1.52,0.15,3.05,0.21,4.58,0.16
c0,0,0.03-3.77-0.08-4.35c-0.07-0.5-0.46-0.89-0.97-0.96c-0.27-0.02-0.52-0.27-0.16-0.23c1.49,0.11,2.99,0.11,4.48,0
c0.48-0.05,0.2,0.21-0.16,0.3c-0.47,0.09-0.85,0.45-0.95,0.92c-0.15,0.58-0.13,4.29-0.13,4.29s3.51,0.04,4.15-0.09
c0.48-0.08,0.86-0.46,0.94-0.94C340.13,441.64,340.38,441.25,340.34,441.57z"/>
<path id="Path_1201" class="st0" d="M308.51,450.59c-1.62-0.79-3.33-1.4-5.09-1.82c-0.56-0.09-0.04-0.24,0.31-0.21
c0.46,0.04,0.85,0.1,1.2-0.25c1.96-3.73,3.55-7.63,4.77-11.66c0.91-2.44-0.32-5.15-2.76-6.06c-0.18-0.07-0.36-0.12-0.55-0.17
c-4-1.43-5.59,0.75-7.77,4.84c-1.58,2.86-2.95,5.84-4.11,8.89c-0.03,0.33,0.12,0.65,0.4,0.83c0.36,0.29,0.56,0.76,0.22,0.49
c-1.39-0.86-2.86-1.58-4.4-2.13c-0.34-0.11-0.07-0.3,0.36-0.21c0.36,0.08,0.52,0,0.87-0.25c2.12-3.33,4.05-6.76,5.81-10.3
c1.05-1.94,2.89-3.34,5.04-3.82c3.29-0.33,6.5,1.08,8.5,3.71c1.19,1.86,1.49,4.16,0.8,6.27c-0.4,1.65-4,9.69-4,10.79
c-0.02,0.31,0.13,0.6,0.4,0.76C308.73,450.45,308.86,450.8,308.51,450.59z"/>
<path id="Path_1202" class="st0" d="M283.31,439.86c0,0-0.75-8.14-0.98-10.95c-0.26-3.27-1.08-9.59-1.08-9.59
s-6.39,6.92-7.22,7.76c-0.83,0.84-1.6,1.67-1.6,2.24c0,0.33,0.13,0.65,0.36,0.9c0.08,0.16,0.22,0.72,0.06,0.52
c-0.55-0.63-1.14-1.22-1.75-1.78c-0.54-0.49-1.1-0.95-1.69-1.37c-0.44-0.29,0.1-0.24,0.34-0.09c0.25,0.19,0.57,0.26,0.88,0.19
c2.46-2.14,4.77-4.45,6.91-6.91c1.71-1.78,5.54-5.99,5.94-6.54c0.28-0.4,0.28-0.22,0.31,0.2c0.04,0.52,0.71,8.89,0.85,9.86
c0.13,0.9,0.56,6.59,0.62,7.23s0.25,2.77,0.25,2.77s2.94-4.22,3.92-5.75c1.19-1.53,2.2-3.2,3.02-4.96
c0.01-0.5-0.24-0.96-0.66-1.23c-0.13-0.14-0.24-0.48,0.06-0.22c1.25,1.05,2.61,1.95,4.05,2.71c0.62,0.29-0.31,0.11-0.47,0.04
c-0.39-0.12-0.81-0.12-1.2,0c-1.87,2.19-3.57,4.52-5.08,6.97c-0.76,1.11-2.98,4.22-3.5,5.07c-0.52,0.84-1.71,2.59-1.95,3.03
C283.47,440.36,283.37,440.33,283.31,439.86z"/>
<path id="Path_1203" class="st0" d="M275.07,405.78c0.44,0.76,0.94,1.48,1.49,2.17c0.57,0.71,1.18,1.37,1.84,2
c0.35,0.33-0.14,0.21-0.46-0.03c-0.32-0.24-0.69-0.35-1.71,0.2c-1.2,0.64-11.68,9.47-12.08,9.99c-0.49,0.6-0.45,0.9-0.24,1.36
c0.16,0.36,0.05,0.67-0.09,0.44c-0.91-1.41-1.95-2.73-3.11-3.94c-0.46-0.34,0.02-0.26,0.32-0.08c0.3,0.17,0.4,0.17,0.76,0
c4.64-3.28,9.06-6.87,13.22-10.75c0.12-0.34,0.08-0.72-0.1-1.03C274.9,405.84,274.84,405.38,275.07,405.78z"/>
<path id="Path_1204" class="st0" d="M265.98,334.45c-0.83,1.65-1.51,3.36-2.03,5.13c-0.1,0.46-0.33-0.02-0.26-0.36
c0.12-0.58,0.2-0.88-0.76-1.52c-4.82-2.22-9.79-4.07-14.88-5.56c-0.42-0.04-0.82,0.18-1.01,0.55c-0.2,0.26-0.62,0.37-0.36,0
c0.79-1.65,1.47-3.35,2.03-5.09c0.09-0.56,0.31,0,0.25,0.32c-0.14,0.37-0.05,0.78,0.23,1.05c5,2.47,10.22,4.48,15.58,5.99
c0.68-0.11,0.61-0.34,0.84-0.55C265.83,334.2,266.3,333.97,265.98,334.45z"/>
<path id="Path_1205" class="st0" d="M261.32,402.92l3.97-5.3c0,0-6.96,0.38-8.45,0.5c-1.49,0.12-5.82,0.31-6.31,1.01
c-0.32,0.47,0,0.99,0,1.15c0.06,0.32,0,0.82-0.16,0.44c-0.08-0.24-0.62-1.65-1.05-2.63c-0.4-0.88-0.9-1.95-1.03-2.15
c-0.22-0.32,0.15-0.24,0.36,0c0.23,0.29,0.57,0.49,0.94,0.56c2.9,0.11,5.81,0.07,8.7-0.12c1.25-0.05,10.45-0.65,11.22-0.58
c0.4,0.04,0.78-0.16,0.28,0.6c-0.28,0.43-5.77,7.62-6.19,8.2c-2.04,2.56-3.92,5.24-5.63,8.02c-0.06,0.36-0.04,0.72,0.06,1.07
c0.06,0.28,0.02,1.05-0.08,0.8c-0.9-1.74-1.93-3.4-3.09-4.99c-0.4-0.51,0.13-0.16,0.44-0.05c0.31,0.12,0.5,0.04,0.85-0.2
C258.04,407.27,259.76,405.15,261.32,402.92z"/>
<path id="Path_1206" class="st0" d="M261.9,376.76c0.26,0.75,1.07,4.05,1.48,5.49c0.14,0.51,1.05,3.87,1.33,4.43
c0.13,0.27-0.47-0.16-0.59-0.44c-0.04-0.22-0.16-0.41-0.35-0.54c-0.19-0.11-0.4-0.17-0.62-0.18c-2.73,0.54-5.42,1.29-8.04,2.22
c-2.63,0.67-5.2,1.59-7.66,2.75c-0.32,0.28-0.43,0.73-0.29,1.13c0.04,0.26-0.16,1.2-0.26,0.61c-0.15-1.04-0.37-2.07-0.64-3.08
c-0.4-1.38-2-7.08-2.07-7.32c-0.13-0.32-0.15-0.44,0.09-0.53c0.72-0.24,1.43-0.52,2.13-0.84c0.5-0.3,0.31,0.13,0.03,0.42
c-0.28,0.29-0.4,0.43-0.36,1.32c0.34,1.68,0.78,3.34,1.33,4.96c0,0,2.35-0.62,3.12-0.9s3.32-1.03,3.32-1.03
c-0.4-1.61-0.9-3.19-1.51-4.74c-0.37-0.49-0.62-0.4-1-0.36c-0.28,0.02-0.76-0.18-0.4-0.26c1.38-0.3,2.72-0.72,4.02-1.25
c0.45-0.22,0,0.34-0.21,0.46c-0.38,0.2-0.6,0.61-0.56,1.04c0.08,0.86,0.28,1.71,0.58,2.53c0.17,0.48,0.65,2.12,0.65,2.12
s4.25-1.23,4.96-1.56c0.71-0.34,1.26-0.34,1.11-1.75c-0.24-1.68-0.75-3.31-1.51-4.83c-0.26-0.41-0.6-0.77-0.99-1.05
c-0.16-0.13-0.72-0.6-0.4-0.49c0.98,0.31,1.94,0.68,2.88,1.1C261.66,376.3,261.82,376.51,261.9,376.76z"/>
<path id="Path_1207" class="st0" d="M282.78,309.83c-0.51,0.54-4.24,4.58-5.29,5.76c-0.35,0.4-1.2,1.35-1.43,1.64
c-0.19,0.22-0.28-0.22-0.12-0.49c0.25-0.29,0.29-0.7,0.12-1.04c-1.98-2.22-4.16-4.24-6.51-6.06c-1.86-1.81-3.89-3.44-6.07-4.86
c-0.4-0.09-0.81-0.03-1.16,0.19c-0.24,0.12-0.8,0.36-0.4-0.03c0.4-0.39,1.02-1.07,1.91-2.04c0.97-1.05,4.96-5.19,5.12-5.41
s0.32-0.28,0.49-0.1c0.5,0.53,1.03,1.03,1.6,1.49c0.6,0.36,0.06,0.32-0.25,0.25c-0.32-0.07-0.43-0.17-1.08,0.21
c-1.27,1.06-2.43,2.24-3.47,3.52l4.77,4.4c0,0,3.32-3.09,3.38-3.72c0.05-0.27,0.03-0.54-0.07-0.8c-0.08-0.25-0.05-0.69,0.16-0.4
c0.77,0.95,1.65,1.82,2.61,2.57c0.4,0.3-0.07,0.3-0.3,0.2c-0.35-0.15-0.48-0.4-1.13-0.08c-1.19,1.06-2.29,2.21-3.31,3.44
c0,0,3.4,2.92,4.04,3.38c0.83,0.61,1.43,0.76,2.26,0c1.23-1.06,2.3-2.28,3.2-3.64c0.2-0.46,0.28-0.97,0.23-1.47
c0.02-0.3,0.2-0.66,0.25-0.42c0.05,0.24,0.75,2.4,0.8,2.75C283.17,309.42,283.09,309.5,282.78,309.83z"/>
<path id="Path_1208" class="st0" d="M260.58,367.65c0.03,0.4,0.13,2.31,0.26,3.16c0.07,0.48-0.22-0.12-0.29-0.36
c-0.04-0.3-0.23-0.56-0.5-0.69c-2.67-0.18-5.35-0.07-7.99,0.34c-2.98,0.1-5.94,0.5-8.84,1.2c-0.31,0.32-0.46,0.76-0.4,1.2
c0,0.26-0.46,1.11-0.45,0.47c0-0.4,0-2.1-0.1-2.7c-0.29-2.05-0.39-4.12-0.3-6.18c0.46-2.23,2.37-3.88,4.65-4
c1.97-0.01,3.76,1.12,4.61,2.89c0.33-0.44,0.74-0.82,1.2-1.12c2.7-1.58,5.24-3.4,7.59-5.46c0.19-0.38,0.24-0.81,0.15-1.23
c-0.06-0.72,0.1-1.23,0.45,0c0.34,1.36,0.15,2.8-0.53,4.03c-1.57,1.59-3.34,2.96-5.27,4.08c-0.8,0.55-2.67,1.6-2.67,2.7
c-0.01,0.54,0.04,1.07,0.15,1.6c0,0,2.74-0.28,3.48-0.36c1.37-0.03,2.73-0.26,4.03-0.7c0.22-0.2,0.35-0.5,0.34-0.8
c0.03-0.21,0.47-1.13,0.44,0.06C260.52,366.18,260.54,367.25,260.58,367.65z M249.41,363.17c-1.94-1.24-4.51-0.73-5.83,1.16
c-0.48,1.23-0.61,2.56-0.37,3.86l3.94-0.26c0.62-0.04,4.06-0.28,4.06-0.28s0.35-3.2-1.8-4.49V363.17z"/>
<path id="Path_1209" class="st0" d="M328.95,307.11c-2.39-2.85-3.7-6.45-3.71-10.16c0.09-2.34,0.98-4.59,2.52-6.36l0.92-1.13
c2.28-2.26,3.59-5.33,3.63-8.55c0.12-2.01-0.11-4.03-0.67-5.96c-0.82,6.44-4.1,12.31-9.16,16.38c-2.28,1.98-6.09,5.28-6.09,9.41
c0.26,4.61,2.07,8.99,5.12,12.45c-0.91-2.36-1.38-4.86-1.38-7.39c-0.02-1.72,0.19-3.43,0.62-5.09l0.07-0.23l0.12,0.21
C322.71,303.76,325.57,306.05,328.95,307.11z"/>
<path id="Path_1210" class="st0" d="M330.13,289.41c2-0.77,9.17-3.91,9.17-8.94c-0.28-3.2-1.64-6.22-3.87-8.54
C337.54,278.29,335.42,285.29,330.13,289.41z"/>
<path id="Path_1211" class="st0" d="M357.06,279.77c-2.69,2.53-5.86,4.47-9.33,5.72l-0.12-0.17c2.95-3.43,4.81-7.66,5.35-12.15
c-5.67,8.93-9.13,10.47-13.13,12.23l-1.75,0.8c-4.79,2.27-10.29,5.51-10.29,10.6c-0.38,3.7,0.72,7.4,3.06,10.29
c-0.43-1.47-0.65-2.98-0.67-4.51c-0.03-1.03,0.1-2.07,0.4-3.06l0.15-0.4l0.06,0.4c1.05,3.22,3.15,6,5.97,7.89
c-0.08-0.8-0.13-1.61-0.12-2.42c0-3.75,0.87-10.39,6.69-12.88C353.83,287.62,356.45,281.82,357.06,279.77z"/>
<path id="Path_1212" class="st0" d="M348.36,300.57c-0.41-3.63,0.3-7.3,2.03-10.52c-7.5,2.91-12.46,10.11-12.51,18.15
c0,0.45,0,0.8,0.04,1.05c1.28-3.54,3.47-6.69,6.35-9.12l0.07-0.06l0.07,0.04c0,0,0.04,0.03,0.04,0.13
c-0.44,2.78-1.02,5.54-1.75,8.26C343.72,307.86,348.36,304.64,348.36,300.57z"/>
<path id="Path_1213" class="st0" d="M358.27,299.89c0-1.47-0.27-2.94-0.8-4.32c-0.48,1.66-1.42,3.15-2.71,4.3l0,0l-0.15-0.15
c0.92-1.44,1.34-3.15,1.17-4.86c-0.01-1.21-0.12-2.41-0.34-3.6c-0.09-0.51-0.14-1.03-0.14-1.55c0.06-2.13,0.69-4.2,1.83-5.99
c-2.9,2.21-4.97,5.33-5.88,8.86c-0.62,2.18-1.11,4.39-1.48,6.62c-0.11,0.79-0.28,1.58-0.51,2.35c-0.8,2.81-1.89,5.54-3.25,8.13
c2.09-1.32,3.75-3.21,4.79-5.45l0.15-0.3l0.06,0.33c0.09,0.68,0.13,1.36,0.12,2.05c0.02,1.94-0.36,3.87-1.11,5.66
C351.51,310.78,358.27,305.09,358.27,299.89z"/>
<path id="Path_1214" class="st0" d="M370.27,288.65c-2.3-1.69-5.24-2.24-7.99-1.49l-0.34,0.11l0.22-0.28
c1.45-1.76,3.21-3.24,5.19-4.36c-3.06-0.62-6.22,0.44-8.29,2.76c-1.27,2.26-1.88,4.83-1.77,7.42c0,0.54,0,0.95,0.04,1.23
c2.32-4.03,2.59-4.02,2.67-4l0.1,0.04v0.08c0.09,0.51,0.13,1.03,0.12,1.55c-0.05,1.76-0.22,3.51-0.52,5.24
C363.83,289.06,368.9,288.61,370.27,288.65z"/>
<path id="Path_1215" class="st0" d="M336.4,428.59l0.43-19c0.29,0.41,0.56,0.84,0.8,1.29c0.33,0.72,0.6,1.48,0.8,2.25
c0.41,0.44,0.69,0.98,0.8,1.57c0.14,0.93,0.58,4.06,0.74,4.79c0.15,0.74,0.14,1.32,0.58,1.32c2.54,0,3.96-4.2,3.42-5.53
c-0.52-1.06-1.18-2.05-1.96-2.93c0,0-1.37-4.35-1.6-4.89c-0.23-0.54-1.22-1.03-1.51-1.22c-0.15-0.1-1.04-0.98-1.9-1.84l0.12-5.33
c-0.28,0.02-0.56,0.02-0.84,0c-2.28,0.03-4.48-0.87-6.09-2.49l0.93,31.99L336.4,428.59z M342.8,418.2
c-1.12,1.56-1.27,1.6-1.66,1.6s-0.4-1.71-0.14-2.59c0.26-0.88,0.88-1.81,1.71-1.76C343.39,415.51,343.93,416.64,342.8,418.2
L342.8,418.2z"/>
<path id="Path_1216" class="st0" d="M378.59,356.33c2.06,0.65,4.2,1.04,6.35,1.17c3.63-0.51,6.98-2.21,9.53-4.84
c1.31-0.91,2.68-1.72,4.1-2.44c0,0-2.64-0.05-5.96-0.34c-3.09-0.25-6.2,0.11-9.14,1.07c-1.67,0.61-3.19,1.58-4.45,2.83
c-0.5,0.57-1.14,0.99-1.86,1.22c-0.98,0.24-1.81,0.44-1.81,0.44c0.23-0.86,0.69-1.63,1.32-2.25c1.72-1.18,3.31-2.54,4.74-4.06
c2.29-2.74,4.23-5.76,5.77-8.98c0.24-0.93,2.25-5.43,2.25-5.43c-1.64,1.17-3.36,2.24-5.13,3.2c-2.82,1.49-5.22,3.65-6.99,6.31
c-1.2,2.26-1.84,4.78-1.86,7.34c-0.14,2.42-1.15,4.71-2.83,6.45c-1.57,1.7-3.27,3.29-5.08,4.74c-0.89,0.68-1.9,1.19-2.98,1.51
c-0.67,0.14-1.37,0.18-2.05,0.1c0,0,1.03-1.32,1.66-1.51c1.74-0.59,3.31-1.58,4.59-2.88c2.04-2.53,3.45-5.51,4.1-8.7
c0.2-0.93,1.07-3.76,1.07-3.76c-1.28,1.22-2.67,2.31-4.16,3.28c-2.62,1.74-4.84,4.02-6.5,6.7c-0.96,1.56-1.26,3.45-0.83,5.23
c0,0.4-0.14,0.64-0.8,1.27c-0.62,0.49-1.36,0.82-2.15,0.93c-1.63,0.6-3.35,0.94-5.09,1.03c-2.03-0.2-4.03-0.57-5.99-1.12
c-0.68-0.05-1.76,0.59-2.2,0.64c-0.41-0.02-0.82-0.07-1.22-0.14c-0.44,0-1.81,0.05-1.81,0.05c0.26-0.72,0.4-1.48,0.44-2.25
c0.05-0.34,0.15-0.83,0.64-0.93c0.83-0.37,1.63-0.79,2.4-1.27c0.44-0.22,0.93-0.32,1.42-0.29c1.89-0.04,3.73-0.55,5.38-1.47
c2.79-1.83,5.13-4.27,6.84-7.14c1.17-1.2,2.45-2.3,3.81-3.28c0,0-2.49,0.68-5.33,1.51c-3.03,0.89-5.88,2.28-8.45,4.11
c-1.11,1.01-2.05,2.18-2.8,3.47c-0.4,0.86-0.9,1.68-1.47,2.44c-0.44,0.34-1.86,1.07-1.86,0.88c0.23-0.63,0.52-1.24,0.88-1.81
c0.34-0.59,1.42-2.3,2.1-3.32c0.53-0.83,0.96-1.71,1.27-2.64c0.29-0.91,0.72-1.76,1.27-2.54c1.08-1.59,2.87-2.56,4.79-2.59
c2.02,0.02,4.05-0.08,6.06-0.3c2.63-0.42,5.13-1.43,7.33-2.93c0.8-0.44,4.25-2.98,4.25-2.98s-3.37,0.59-4.45,0.73
c-2.56,0.11-5.1,0.38-7.63,0.8c-2.34,0.75-4.54,1.89-6.5,3.37c-1.44,0.99-2.83,2.06-4.15,3.2c0-0.62,0.05-1.24,0.15-1.86
c0.11-0.82,0.6-1.55,1.32-1.96c2.01-1.1,3.88-2.44,5.57-4c1.77-1.95,3.25-4.13,4.4-6.5c0.3-0.88,2.05-4.4,2.05-4.4
c-1.18,1-2.49,1.82-3.91,2.45c-2.89,1.41-5.46,3.4-7.53,5.87c-1.14,1.39-1.82,3.1-1.95,4.89c-0.03,0.8-0.16,1.58-0.4,2.35
c-0.39,0.77-0.59,1.63-0.59,2.49c-0.05,0.96-0.26,1.91-0.64,2.8c-0.15,0.61-0.36,1.2-0.64,1.76c-0.26,0.34-0.48,0.72-0.64,1.12
c-0.68,1.15-1.45,2.24-2.3,3.28c0,0-0.64-0.8,0.34-2.88c1.12-2.23,1.8-4.65,2-7.14c-0.1-2.03-0.48-4.04-1.13-5.96
c-0.44-1.17-1.91-5.33-1.91-5.33c-0.13,1.32-0.41,2.61-0.83,3.86c-1.16,2.76-1.92,5.67-2.25,8.65c0.1,2.41,0.82,4.75,2.11,6.79
c0.62,0.75,0.89,1.73,0.73,2.69c-0.11,0.86-0.47,1.68-1.03,2.35c-0.36,0.72-0.6,1.5-0.68,2.3c-0.43,2.01-1.67,3.76-3.42,4.84
c-0.15,0.12-0.34,0.26-0.55,0.4l0.69-26.82c-0.01-6.13,1.5-12.17,4.4-17.58c0.47-0.68,0.72-1.01,0.72-1.01
c2.17-2.98,5.52-4.9,9.19-5.27v-2.19c0,0-16.85-0.03-20.13-0.03h-0.06c-3.26,0-18.44,0.03-18.44,0.03v2.19
c3.67,0.37,7.02,2.29,9.19,5.27c2.88,4,4.66,6.37,5.17,19.07l0.93,30.65c-1.35,0.86-2.27,2.26-2.53,3.85
c-0.4-0.59-0.49-1.33-0.24-2c0.84-1.83,1.13-3.87,0.83-5.87c-0.94-2.95-2.41-5.7-4.35-8.12c-0.93-1.07-2.64-3.71-2.64-3.71
s0.05,2.45-0.1,4.4c-0.53,2.69-0.41,5.47,0.34,8.11c0.77,2.19,2.21,4.09,4.1,5.43c0.61,0.49,1.01,1.19,1.12,1.96
c0.15,0.66,0.11,1.35-0.1,2c-0.02,0.72-0.11,1.44-0.24,2.15c-0.2,0.72-0.8,1.12-0.88,1.76c-0.17,1.01-0.41,2.01-0.73,2.98
c-0.15,0.54-0.49,0.64-0.93,1.37c-0.25,0.36-0.37,0.79-0.34,1.22c-0.94-0.76-1.8-1.63-2.54-2.59c-1.08-2.96-3.64-5.14-6.74-5.72
c-2.1-0.34-4.24-0.38-6.35-0.14c-1.78-0.04-3.56-0.25-5.31-0.63c1.53,0.49,2.89,1.43,3.89,2.69c1.89,2.1,4.2,3.77,6.79,4.89
c1.68,0.5,3.47,0.48,5.13-0.05c0.73-0.19,1.27-0.49,1.91-0.24c0.54,0.31,1,0.72,1.37,1.22c0,0-1.13,0.64-1.96,1.03
c-2.86,1-5.32,2.9-6.99,5.43c-0.88,2.14-1.52,4.37-1.91,6.65c-0.28,1.27-0.62,2.53-1.03,3.76c0,0,1.66-1.42,3.03-2.35
c2.13-1.27,4.02-2.9,5.57-4.84c1.55-2.38,2.44-5.13,2.59-7.97c0-0.57,0.42-1.05,0.98-1.13c0.58,0.18,0.99,0.71,1.03,1.32
c0.01,0.7,0.23,1.39,0.64,1.96c0.29,0.44,0.98,1.03,1.57,1.86c0.55,1.13,1.02,2.29,1.42,3.47c0.4,0.8,0.59,0.68,1.17,1.76
c0.59,1.07,0.49,1.66,0.98,2.49c0.49,0.83,0.73,0.74,0.73,0.74l-0.29-5.19c-0.15-0.09-0.29-0.2-0.4-0.34
c-0.19-0.28-0.35-0.57-0.49-0.88c0,0,0.88-0.59,1.47-0.88c0.42-0.25,0.94-0.21,1.32,0.1c1.78,1.42,3.94,2.28,6.21,2.49
c3.65-0.72,7.15-2.04,10.36-3.91c1.32-0.56,2.68-1.04,4.06-1.42c0,0-2.93-0.29-4.5-0.64c-2.37-0.53-4.77-0.94-7.19-1.22
c-0.67,0.01-1.34,0.09-2,0.24l0.13-1.57c0,0-1.29,1.09-1.73,1.43c-1.01,0.66-2.09,1.2-3.23,1.6c-0.76,0.29-1.55,0.52-2.35,0.68
c0,0-0.2-0.2-0.34,0.54s-0.24,0.64-1.07,0.83c-0.54,0.13-1.06,0.31-1.56,0.54c0,0,0.68-1.76,0.8-2.05
c0.12-0.29,0.24-0.58,1.27-0.8c2.61-0.53,5.03-1.76,6.99-3.57c2.16-2.06,3.87-4.54,5.03-7.28c0.93-1.6,2.1-3.05,3.47-4.3
c0,0-2.25,0.88-6.5,2.35c-0.2,0.07-0.4,0.14-0.59,0.22l0.15-5.61l0,0v-0.4l-0.29,0.14c-0.64,0.29-2.49,0.83-3.22,1.17
c-0.73,0.34-1.32,1.12-1.91,1.42c-1.03,0.38-1.97,0.96-2.76,1.71l0.05,0.92l0,0l0.19,5.99c-1.1,1.43-1.77,3.15-1.92,4.94
c-0.2,1.12-0.34,1.66-0.49,2.25c-0.21,0.66-0.45,1.32-0.73,1.96c-0.46-0.89-1.02-1.73-1.66-2.49c-0.57-0.62-0.74-1.51-0.44-2.3
c0.23-0.87,0.54-1.73,0.93-2.54c0.44-1.12,1.03-3.28,1.37-3.96c0.34-0.68,0.2,0.64,0.93-3.37c0.43-2.45,2.18-4.46,4.55-5.23
c0.59-0.3,1.17-1.07,1.91-1.42c0.73-0.34,2.59-0.88,3.22-1.17c1.39-0.53,2.64-1.37,3.67-2.45c0.54-0.84,1.28-1.52,2.15-2
c1.05-0.36,2.16-0.53,3.27-0.49c1.6-0.1,1.95,1.17,2.3,1.6c0.29,0.43,0.43,0.95,0.4,1.47c-0.15,2.49,0.93,4.9,2.88,6.45
c2.56,1.91,5.58,3.11,8.75,3.47c1.47,0.4,5.13,1.91,5.13,1.91s-0.64-0.24-3.13-4.11c-1.61-2.77-3.79-5.17-6.39-7.03
c-1.56-0.74-3.21-1.29-4.9-1.63c-0.58-0.1-1.13-0.33-1.6-0.68c-0.45-0.49-0.85-1.01-1.22-1.57c0.21-0.03,0.42-0.03,0.64,0
c1.54,0.67,3.21,0.99,4.89,0.93c1.97,0.01,3.92-0.46,5.67-1.37c0.63-0.25,1.34-0.18,1.91,0.2c0.64,0.4,1.42,0.93,2.98,1.91
c2.16,1.46,4.68,2.32,7.28,2.49c3.15-0.19,6.25-0.86,9.19-2c1.23-0.5,2.51-0.9,3.81-1.17c0,0-2.44-0.44-3.81-0.74
c-2.9-0.98-5.9-1.63-8.95-1.95c-2.01,0.01-3.97,0.59-5.67,1.66c-0.52,0.54-1.31,0.7-2,0.4c-0.71-0.14-1.28-0.64-1.51-1.32
c2.01-0.09,3.94-0.81,5.52-2.05c1.32-1.06,2.54-2.26,3.62-3.57c0.63-0.6,1.14-1.35,2.49-2.59
C375.76,356.13,377.27,355.8,378.59,356.33z M385.7,351.25c3.16-0.63,6.39-0.75,9.59-0.36c-0.8,0.2-5.67,2.3-9.09,3.2
c-2.43,0.6-4.9,0.99-7.4,1.17l-0.05-0.1C380.74,353.36,383.12,352.02,385.7,351.25z M378.35,344.26c2.09-2.87,4.93-5.1,8.22-6.43
c0,0-4.19,5.57-5.51,7.35c-1.33,1.79-4.75,6.84-4.75,6.84c-0.11-2.73,0.61-5.44,2.06-7.76H378.35z M364.66,356.77
c1.82-2.64,4.26-4.79,7.1-6.28c0,0-2.91,4.9-4.54,7.15c-1.63,2.25-4,5-4,5s-0.94-1.94,1.46-5.87H364.66z M351.85,354.32
c2.79-1.51,5.69-2.81,8.68-3.88c0,0-5,4.44-7.5,6.23c-1.75,1.21-3.6,2.29-5.51,3.22c0.82-2.27,2.35-4.22,4.36-5.57L351.85,354.32
z M359.97,344.36c2.9-0.57,5.84-0.89,8.79-0.97c0,0-5.77,2.04-8.12,2.8c-2.13,0.6-4.3,1.06-6.48,1.38
c1.76-1.37,3.73-2.46,5.83-3.21L359.97,344.36z M352.25,340.08c2.44-2.6,5.33-4.74,8.53-6.33c0,0-3.73,3.72-6.33,6.79
c-2.6,3.07-4.34,5.16-4.34,5.16l-0.05,0.1c0.34-2.04,1.09-3.99,2.21-5.73L352.25,340.08z M343.37,355.8
c-1.25-1.97-1.91-4.25-1.89-6.58c0.16-2.96,0.96-5.85,2.35-8.47c0,0-0.1,4.79,0.05,7.5c0.01,2.52-0.15,5.05-0.5,7.55
L343.37,355.8z M311.81,384.09c-2.02-0.85-3.95-1.89-5.77-3.12c2.84-0.4,5.73-0.26,8.53,0.4c2.17,0.87,3.84,2.67,4.54,4.9
c0,0-4.93-1.36-7.27-2.19L311.81,384.09z M310.8,402.47c0.31-2.93,1.17-5.78,2.54-8.39c1.3-1.77,3.15-3.06,5.27-3.65
L310.8,402.47z M338.47,391.52c2.83,0.11,5.64,0.5,8.39,1.15c-3.22,0.78-6.48,1.37-9.77,1.77c-2.06,0.14-4.13,0.11-6.19-0.08
c0,0,1.56-2.26,7.6-2.86L338.47,391.52z M332.12,383.39c2.86-1.96,6.01-3.46,9.34-4.44c0,0-5.61,4.79-7.86,6.79
c-1.81,1.7-3.51,3.51-5.1,5.41c-0.01-3.01,1.33-5.86,3.66-7.78L332.12,383.39z M325.9,374.99c-1.1-1.94-1.97-3.99-2.6-6.13
c-0.68-2.48-1.69-8.47-1.69-8.47c1.72,2.42,3.27,4.96,4.65,7.59c0.65,2.31,0.53,4.77-0.33,7L325.9,374.99z M350.15,368.87
c2.12,0.47,4.16,1.23,6.07,2.25c2.74,2.11,4.96,4.81,6.48,7.91c-2.44-1.33-4.8-2.81-7.04-4.44c-2.04-1.64-3.89-3.51-5.51-5.57
V368.87z M371.89,365.45c3.08,0.22,6.12,0.84,9.03,1.84c0,0-6.84,0.87-9.03,0.87c-1.97-0.07-3.93-0.26-5.87-0.56
c1.74-1.22,3.78-1.96,5.9-2.15L371.89,365.45z"/>
<path id="Path_1217" class="st0" d="M361.37,338.3c-0.91,0.5-1.44,1.51-1.33,2.55c-0.12,0.71,0.36,1.39,1.08,1.51
c0.23,0.04,0.48,0.01,0.7-0.07c1.01-0.3,1.66-1.27,1.55-2.32c0.04-0.89-0.65-1.66-1.54-1.7
C361.67,338.25,361.52,338.27,361.37,338.3z"/>
<path id="Path_1218" class="st0" d="M385.58,345.63c-0.91,0.5-1.44,1.5-1.33,2.54c-0.12,0.71,0.35,1.39,1.06,1.51
c0.24,0.04,0.48,0.02,0.71-0.07c1.01-0.3,1.67-1.28,1.55-2.33c0.04-0.9-0.65-1.65-1.55-1.7
C385.88,345.58,385.73,345.6,385.58,345.63z"/>
<path id="Path_1219" class="st0" d="M344.59,368.63c-0.91,0.51-1.43,1.51-1.33,2.55c-0.12,0.71,0.35,1.38,1.06,1.51
c0.24,0.04,0.48,0.02,0.71-0.08c1.01-0.3,1.66-1.27,1.55-2.32c0.04-0.9-0.65-1.66-1.55-1.71
C344.89,368.58,344.74,368.6,344.59,368.63z"/>
<path id="Path_1220" class="st0" d="M373.24,360.94c-0.33,0.64-0.08,1.43,0.56,1.77c0.21,0.11,0.45,0.16,0.68,0.14
c1.05,0.02,1.97-0.71,2.18-1.74c0.32-0.84-0.1-1.77-0.94-2.09c-0.15-0.06-0.3-0.09-0.45-0.1
C374.26,359.12,373.45,359.92,373.24,360.94z"/>
<path id="Path_1221" class="st0" d="M360.92,368.61c-0.91,0.51-1.43,1.51-1.33,2.55c-0.12,0.71,0.36,1.39,1.07,1.51
c0.24,0.04,0.48,0.02,0.7-0.07c1.01-0.3,1.66-1.28,1.55-2.33c0.04-0.9-0.65-1.66-1.55-1.7
C361.22,368.57,361.07,368.58,360.92,368.61z"/>
<path id="Path_1222" class="st0" d="M341.44,385.33c-0.91,0.5-1.44,1.5-1.33,2.54c-0.13,0.71,0.35,1.39,1.06,1.52
c0.24,0.04,0.48,0.02,0.71-0.07c1.01-0.3,1.66-1.28,1.55-2.33c0.04-0.9-0.65-1.65-1.55-1.7
C341.73,385.28,341.58,385.3,341.44,385.33z"/>
<path id="Path_1223" class="st0" d="M311.04,392.41c1.01-0.3,1.66-1.28,1.55-2.33c0.04-0.9-0.65-1.66-1.55-1.7
c-0.15-0.01-0.3,0.01-0.45,0.04c-0.91,0.51-1.44,1.51-1.33,2.55c-0.12,0.71,0.36,1.39,1.07,1.51
C310.57,392.52,310.82,392.5,311.04,392.41z"/>
<path id="Path_1224" class="st0" d="M320.23,271.21c1.67,2.3,2.61,5.05,2.72,7.89c0,1.07-0.12,2.8-0.12,2.8
c-0.17,1.67-0.48,3.32-0.93,4.93c1.49-2.11,2.64-4.43,3.43-6.89l0.06-0.27l0.13,0.24c0.54,1.04,0.89,2.17,1.02,3.34
c0.63-1.45,0.98-3,1.02-4.58C327.24,274.74,324.16,271.6,320.23,271.21z"/>
<path id="Path_1225" class="st0" d="M321.12,283.36L321.12,283.36c-0.07-1.23-0.21-2.46-0.43-3.68c-1.7,3.43-4.15,6.43-7.16,8.79
c-2.79,1.95-4.55,5.06-4.79,8.45c0.56,5.03,3.14,9.61,7.15,12.69c-1.24-3.34-1.89-6.88-1.93-10.44c0.12-1.87,1.04-3.59,2.53-4.73
l0.3-0.3c1.12-1.06,2.14-2.21,3.05-3.46l0,0c0.48-0.72,0.84-1.51,1.06-2.34c0.09-0.39,0.15-0.8,0.19-1.2l0,0
C321.18,285.88,321.2,284.62,321.12,283.36z"/>
<path id="Path_1226" class="st0" d="M290.99,341.24c-0.91,0-1.65,0.74-1.65,1.65c0,0.01,0,0.01,0,0.02
c0.01,0.41,0.18,0.79,0.47,1.08c-0.19-0.06-0.39-0.1-0.59-0.1c-1.15,0-2.07,0.94-2.07,2.08c0,1.14,0.93,2.06,2.07,2.07
c0.18-0.01,0.37-0.03,0.55-0.08c-0.46,1.51-1.87,2.53-3.44,2.51c-3.05,0-4.27-3.29-4.4-4.07c0.32,1.08,1.45,1.71,2.54,1.39
c1.08-0.32,1.71-1.45,1.39-2.54c-0.26-0.87-1.06-1.47-1.97-1.47c-0.21,0.01-0.41,0.05-0.61,0.12c0.84-0.75,0.92-2.04,0.17-2.89
c-0.75-0.84-2.04-0.92-2.89-0.17c-0.43,0.38-0.68,0.93-0.69,1.51c0.01,0.6,0.27,1.17,0.72,1.57c-0.21-0.08-0.44-0.13-0.67-0.14
c-1.13-0.01-2.06,0.9-2.07,2.04c-0.01,1.13,0.9,2.06,2.04,2.07c0.92,0.01,1.74-0.6,1.99-1.49c-0.12,0.94-1.84,4.07-4.4,4.07
c-1.59,0.06-3.02-0.97-3.46-2.51c0.18,0.05,0.36,0.07,0.55,0.08c1.15,0,2.07-0.94,2.07-2.08c0-1.14-0.93-2.06-2.07-2.07
c-0.2,0-0.4,0.03-0.59,0.1c0.29-0.28,0.46-0.67,0.47-1.08c0.01-0.91-0.73-1.66-1.64-1.66c-0.01,0-0.02,0-0.02,0
c-0.36-0.04-0.72,0.03-1.04,0.2c0.43,1.7,0.94,5.11,1.02,5.59l1.43,9.31h15.38c0,0,0-0.16,0.04-0.28l1.39-9.04
c0.31-2.11,0.68-4.34,1-5.59C291.7,341.27,291.34,341.2,290.99,341.24z"/>
<path id="Path_1227" class="st0" d="M320.05,341.24c-0.91,0-1.64,0.74-1.64,1.65c0,0,0,0.01,0,0.01
c0.01,0.41,0.18,0.79,0.47,1.08c-0.19-0.06-0.39-0.1-0.59-0.1c-1.15,0-2.07,0.94-2.07,2.08c0,1.14,0.93,2.06,2.07,2.07
c0.18-0.01,0.37-0.03,0.55-0.08c-0.46,1.51-1.87,2.53-3.44,2.51c-3.05,0-4.27-3.29-4.4-4.07c0.32,1.08,1.45,1.71,2.54,1.39
c1.08-0.32,1.71-1.45,1.39-2.54c-0.26-0.87-1.06-1.47-1.97-1.47c-0.21,0.01-0.41,0.05-0.61,0.12c0.84-0.75,0.92-2.04,0.17-2.89
c-0.75-0.84-2.04-0.92-2.89-0.17c-0.43,0.38-0.68,0.93-0.69,1.51c0.01,0.6,0.27,1.17,0.72,1.57c-0.21-0.08-0.44-0.13-0.67-0.14
c-1.13-0.01-2.06,0.9-2.07,2.04c-0.01,1.13,0.9,2.06,2.04,2.07c0.92,0.01,1.74-0.6,1.99-1.49c-0.12,0.94-1.84,4.07-4.4,4.07
c-1.59,0.06-3.02-0.97-3.46-2.51c0.18,0.05,0.36,0.07,0.55,0.08c1.15,0,2.07-0.94,2.07-2.08c0-1.14-0.93-2.06-2.07-2.07
c-0.2,0-0.4,0.03-0.59,0.1c0.29-0.28,0.46-0.67,0.47-1.08c0.01-0.91-0.73-1.66-1.64-1.66c-0.01,0-0.02,0-0.03,0
c-0.36-0.04-0.72,0.03-1.04,0.2c0.43,1.7,0.94,5.11,1.02,5.59l1.43,9.31h15.38c0,0,0-0.16,0.04-0.28l1.39-9.04
c0.31-2.11,0.72-4.47,1-5.59C320.77,341.27,320.41,341.2,320.05,341.24z"/>
<path id="Path_1228" class="st0" d="M306.66,359.85c-1,0-1.81,0.81-1.81,1.81c0,0.01,0,0.01,0,0.02c0.01,0.45,0.19,0.88,0.52,1.2
c-1.21-0.36-2.48,0.32-2.84,1.53c-0.36,1.21,0.32,2.48,1.53,2.84c0.21,0.06,0.44,0.1,0.66,0.1c0.2-0.01,0.41-0.04,0.6-0.09
c-0.51,1.66-2.06,2.79-3.8,2.76c-3.37,0-4.71-3.63-4.83-4.49c0.35,1.2,1.61,1.88,2.8,1.53c1.2-0.35,1.88-1.61,1.53-2.8
c-0.28-0.96-1.17-1.63-2.17-1.62c-0.23,0.01-0.45,0.05-0.67,0.13c0.93-0.83,1.02-2.25,0.19-3.19c-0.83-0.93-2.25-1.02-3.19-0.19
c-0.48,0.42-0.75,1.03-0.76,1.67c0.01,0.66,0.3,1.29,0.8,1.73c-0.23-0.09-0.48-0.14-0.73-0.15c-1.25-0.01-2.27,0.99-2.28,2.25
c-0.01,1.25,0.99,2.27,2.25,2.28c1.02,0.01,1.91-0.66,2.2-1.64c-0.13,1.03-2.03,4.49-4.85,4.49c-1.76,0.06-3.33-1.07-3.82-2.76
c0.2,0.05,0.4,0.08,0.6,0.09c1.26,0.05,2.33-0.93,2.38-2.19c0.05-1.26-0.93-2.33-2.19-2.38c-0.06,0-0.13,0-0.19,0
c-0.22,0-0.44,0.04-0.65,0.11c0.33-0.31,0.51-0.75,0.52-1.2c0.01-1-0.8-1.83-1.8-1.83c-0.01,0-0.02,0-0.03,0
c-0.39-0.05-0.79,0.03-1.14,0.22c0.48,1.88,1.03,5.63,1.12,6.15l1.57,10.27h16.96c0,0,0.02-0.17,0.04-0.3l1.53-9.99
c0.34-2.33,0.8-4.94,1.1-6.15C307.45,359.86,307.05,359.79,306.66,359.85z"/>
</g>
</g>
<g>
<path class="st0" d="M292.05,156.13h-5.16c-0.07,6.74-0.14,13.42-0.14,24.7c0,5.99,0.41,9.36,2.41,11.83
c1.93,2.41,5.43,3.44,10.39,3.44c4.82,0,8.53-1.17,10.73-4.06c2-2.62,2.06-6.74,2.13-13.28l0.14-22.63h-5.99v-4.34h16.65v4.34
h-5.3l-0.14,26.08c0,5.5-0.62,9.49-3.78,13.35c-2.75,3.37-7.84,5.23-14.65,5.23c-8.39,0-13-2.13-15.82-5.99
c-2.27-3.1-2.68-6.47-2.68-14.52c0-7.84,0.07-16.79,0.14-24.15h-5.57v-4.34h16.65V156.13z"/>
<path class="st0" d="M350.99,195.62h4.54c0-5.5,0.28-11.28,0.28-16.99c0-3.44-0.14-10.32-8.05-10.32
c-5.02,0-10.53,3.03-10.53,12.66l-0.14,14.65h5.16v4.33h-15.41v-4.33h4.54l0.28-26.83h-5.71v-4.33h11.35
c0,1.38-0.07,3.3-0.21,4.27l-0.55,3.58h0.14c1.51-5.37,7.22-8.67,12.59-8.67c9.77,0,12.18,6.6,12.18,13.35
c0,6.05-0.27,13.14-0.27,18.65h5.23v4.33h-15.41V195.62z"/>
<path class="st0" d="M376.65,168.79h-6.47v-4.33h12.11l-0.28,31.17h5.64v4.33h-16.92v-4.33h5.64L376.65,168.79z M378.79,146.5
c2.34,0,4.27,1.93,4.27,4.27c0,2.34-1.93,4.27-4.27,4.27c-2.34,0-4.27-1.93-4.27-4.27C374.52,148.42,376.45,146.5,378.79,146.5z"
/>
<path class="st0" d="M387.85,164.45h14.59v4.33h-4.27l8.19,22.77c0.34,0.96,0.55,2,0.76,3.03h0.14c0.21-1.03,0.41-2.06,0.76-3.03
l8.39-22.77h-4.61v-4.33h14.17v4.33h-3.92l-12.25,31.17h-5.64l-12.32-31.17h-3.99V164.45z"/>
<path class="st0" d="M433.97,182.68c0.21,7.29,3.37,13.42,13.48,13.42c3.85,0,7.7-1.17,10.66-2.68l-0.21,4.88
c-2.61,1.31-8.12,2.48-11.7,2.48c-11.21,0-18.16-6.12-18.16-18.51c0-10.46,5.64-18.64,16.44-18.64
c14.04,0,15.34,12.73,15.34,19.06H433.97z M453.92,178.35c0-5.57-3.51-10.39-9.43-10.39c-6.05,0-10.18,4.54-10.52,10.39H453.92z"
/>
<path class="st0" d="M470.71,168.79h-6.05v-4.33h11.7v1.93c0,2.06-0.41,6.26-0.76,9.15h0.07h0.14c1.38-5.23,3.23-11.7,12.04-11.7
c0.48,0,3.3,0.28,3.58,0.55l-0.55,5.09c-0.96-0.34-2.48-0.55-3.85-0.55c-7.29,0-10.53,7.16-10.66,13.42l-0.28,13.28h5.99v4.33
h-16.65v-4.33h5.02L470.71,168.79z"/>
<path class="st0" d="M519.81,174.29h-5.09l-0.28-5.02c-1.31-1.1-4.61-1.31-6.26-1.31c-3.58,0-8.19,1.17-8.19,5.44
c0,3.85,3.44,5.02,8.67,5.92c9.01,1.51,12.8,4.27,12.8,10.11c0,6.33-4.27,11.35-14.52,11.35c-3.85,0-9.97-0.96-12.18-2.13
l-0.27-9.08h5.09l0.27,5.3c2.13,1.03,5.71,1.58,8.05,1.58c3.72,0,8.19-1.58,8.19-5.92c0-3.51-3.65-4.75-7.5-5.57
c-9.49-2.06-14.24-3.72-14.24-10.66c0-5.71,3.79-10.66,13.97-10.66c2.96,0,8.46,0.96,11.21,2.13L519.81,174.29z"/>
<path class="st0" d="M532.86,168.79h-6.47v-4.33h12.11l-0.28,31.17h5.64v4.33h-16.92v-4.33h5.64L532.86,168.79z M534.99,146.5
c2.34,0,4.27,1.93,4.27,4.27c0,2.34-1.93,4.27-4.27,4.27c-2.34,0-4.27-1.93-4.27-4.27C530.72,148.42,532.65,146.5,534.99,146.5z"
/>
<path class="st0" d="M546.4,164.45h5.71l0.27-8.67l5.64-0.34l-0.27,9.01h11.15v4.33h-11.22c-0.14,5.92-0.27,11.9-0.27,17.82
c0,5.09,0,9.5,5.44,9.5c2.89,0,5.5-0.83,7.02-1.44l-0.21,4.47c-1.79,0.89-5.09,1.65-7.98,1.65c-9.91,0-9.91-7.09-9.91-11.63
c0-4.34,0.21-15.21,0.28-20.37h-5.64V164.45z"/>
<path class="st0" d="M571.76,164.45h15v4.33h-4.47l8.46,22.08c0.41,1.24,0.83,2.89,0.96,3.72h0.14c0.14-0.83,0.55-2.48,0.96-3.72
l7.91-22.08h-5.02v-4.33h14.17v4.33h-3.92l-10.87,29.93c-5.02,13.97-9.08,19.33-18.03,19.33c-1.72,0-3.16-0.27-4.2-0.62v-4.68
c0.83,0.28,2.61,0.62,3.99,0.62c4.06,0,8.26-2.48,10.94-8.94l1.17-2.89l-13-32.75h-4.2V164.45z"/>
<path class="st0" d="M276.94,127.75h5.66v6.56c2.21,1.31,6.42,1.79,9.46,1.79c6.9,0,11.46-3.18,11.46-8.98
c0-12.91-26.52-5.25-26.52-22.58c0-5.87,3.45-13.74,17.88-13.74c3.52,0,9.94,0.9,12.98,2.28v9.74h-5.38v-6.01
c-1.8-0.76-5.8-1.31-8.08-1.31c-5.18,0-11.05,2-11.05,8.36c0,12.29,26.52,4.63,26.52,22.44c0,10.63-9.12,14.5-18.44,14.5
c-7.94,0-11.81-1.86-14.5-2.42V127.75z"/>
<path class="st0" d="M314.23,104.34h5.73l0.28-8.7l5.66-0.34l-0.28,9.04h11.19v4.35h-11.25c-0.14,5.94-0.28,11.95-0.28,17.88
c0,5.11,0,9.53,5.46,9.53c2.9,0,5.52-0.83,7.04-1.45l-0.21,4.49c-1.79,0.9-5.11,1.66-8.01,1.66c-9.94,0-9.94-7.11-9.94-11.67
c0-4.35,0.21-15.26,0.28-20.44h-5.66V104.34z"/>
<path class="st0" d="M358.07,103.51c10.84,0,17.26,7.46,17.26,17.68c0,11.33-6.42,19.61-17.26,19.61
c-10.84,0-17.26-7.46-17.26-17.67C340.8,111.79,347.23,103.51,358.07,103.51z M358.07,136.1c7.6,0,11.33-6.21,11.33-13.95
c0-7.73-3.73-13.95-11.33-13.95c-7.59,0-11.32,6.21-11.32,13.95C346.74,129.89,350.47,136.1,358.07,136.1z"/>
<path class="st0" d="M409.78,139.07c-2.76,0.83-6.35,1.73-10.29,1.73c-14.09,0-18.58-9.32-18.58-18.64
c0-13.6,9.87-18.64,17.82-18.64c3.94,0,7.87,0.48,11.53,1.79v9.32h-5.11v-5.59c-1.52-0.55-4.35-0.83-5.94-0.83
c-10.29,0-12.36,8.15-12.36,13.95c0,1.93,0.28,13.95,13.53,13.95c3.52,0,6.35-0.97,9.67-2L409.78,139.07z"/>
<path class="st0" d="M420.15,91.22h-6.91v-4.35h12.57l-0.14,33.14l13.6-11.19v-0.14h-4.97v-4.35h15.47v4.35h-3.66l-14.78,12.02
l16.09,14.92h3.87v4.35h-15.47v-4.35h4.28v-0.14l-14.43-13.74l-0.14,13.88h4.7v4.35h-15.47v-4.35h5.11L420.15,91.22z"/>
<path class="st0" d="M460.4,91.22h-6.91v-4.35h12.57L466,105.58c0,1.59-0.41,5.11-0.69,6.63h0.14c1.52-5.39,7.25-8.7,12.64-8.7
c9.81,0,12.22,6.63,12.22,13.39c0,6.08-0.28,13.19-0.28,18.71h5.25v4.35h-15.47v-4.35h4.56c0-5.53,0.27-11.33,0.27-17.06
c0-3.45-0.14-10.36-8.08-10.36c-5.04,0-10.57,3.04-10.57,12.71l-0.21,14.71h5.25v4.35h-16.02v-4.35h5.11L460.4,91.22z"/>
<path class="st0" d="M516.3,103.51c10.84,0,17.26,7.46,17.26,17.68c0,11.33-6.42,19.61-17.26,19.61
c-10.84,0-17.26-7.46-17.26-17.67C499.04,111.79,505.46,103.51,516.3,103.51z M516.3,136.1c7.6,0,11.32-6.21,11.32-13.95
c0-7.73-3.73-13.95-11.32-13.95c-7.6,0-11.32,6.21-11.32,13.95C504.98,129.89,508.7,136.1,516.3,136.1z"/>
<path class="st0" d="M542.77,91.22h-6.91v-4.35h12.57l-0.28,48.75h5.66v4.35h-16.43v-4.35h5.11L542.77,91.22z"/>
<path class="st0" d="M558.84,135.62h4.56l0.27-26.93h-5.73v-4.35h11.39c0,1.38-0.07,3.32-0.21,4.28l-0.55,3.59h0.14
c1.52-5.39,7.25-8.7,12.64-8.7c6.49,0,9.87,3.73,10.77,8.35h0.14c0.69-1.52,2.9-8.35,12.08-8.35c9.8,0,12.22,6.63,12.22,13.39
c0,6.08-0.28,13.19-0.28,18.71h5.25v4.35h-15.47v-4.35h4.56c0.07-5.8,0.27-11.53,0.27-17.26c0-5.18-1.11-10.15-7.73-10.15
c-4.63,0-10.15,3.04-10.22,12.71l-0.14,14.71h5.11v4.35h-15.54v-4.35h4.55c0.07-5.8,0.28-11.53,0.28-17.26
c0-5.18-1.1-10.15-7.73-10.15c-4.63,0-10.15,3.04-10.22,12.71l-0.14,14.71h5.18v4.35h-15.47V135.62z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -5,17 +5,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Management - Seshat App</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.9.1/font/bootstrap-icons.min.css">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.9.1/font/bootstrap-icons.min.css">
<link rel="stylesheet" th:href="@{/css/styles.css}">
</head>
<body>
<header class="header bg-primary text-white py-3">
<div class="container d-flex justify-content-between align-items-center">
<img th:src="@{/images/SU_logotyp_Landscape_Invert.svg}" alt="Stockholm University Logotype" class="logo">
<h1 class="app-title mb-0">Seshat Audio Transcriber</h1>
<div th:if="${#authentication.name != 'anonymousUser'}" class="dropdown">
<a class="user-menu text-white text-decoration-none dropdown-toggle" href="#" id="userMenu" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<a class="user-menu text-white text-decoration-none dropdown-toggle" href="#" id="userMenu" role="button"
data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-person-circle"></i>
<span th:text="${#authentication.name}">Username</span>
<span th:text="${#authentication.getName()}">Username</span>
</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userMenu">
<li><a class="dropdown-item" th:href="@{/logout}">Logout</a></li>
@ -55,60 +58,90 @@
<!-- File Status Section -->
<section th:if="${statuses != null && !statuses.isEmpty()}" class="mt-5">
<h3>File Upload Statuses</h3>
<ul class="list-group">
<li th:each="status : ${statuses}" class="list-group-item d-flex justify-content-between align-items-center">
<span th:text="${status.fileName}">File Name</span>
<div class="table-wrapper">
<table class="table">
<thead>
<tr>
<th>File Name</th>
<th>Upload Date</th>
<th>Upload time</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr th:each="status : ${statuses}">
<td th:text="${status.fileName}">File Name</td>
<td th:text="${#temporals.format(status.getUploadedAt(), 'yyyy-MM-dd')}">Upload Date</td>
<td th:text="${#temporals.format(status.getUploadedAt(), 'HH:mm:ss')}">Upload time</td>
<td>
<span class="badge bg-primary" th:text="${status.jobStatus}">Status</span>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
</section>
<hr>
<!-- File Browsing Section -->
<section>
<h3>Your Files</h3>
<h3>Your Transcribed Files</h3>
<form id="bulk-actions-form" method="post">
<div th:each="entry : ${filesByDirectory}">
<a data-bs-toggle="collapse"
th:href="'#collapse-' + ${entry.key.id}">
<i class="bi bi-folder"></i> <span th:text="${entry.key.fileName}">Directory Name</span>
</a>
(uploaded at: <span th:text="${#temporals.format(entry.key.getUploadedAt(), 'yyyy-MM-dd HH:mm:ss')}"></span>)
<div th:id="'collapse-' + ${entry.key.id}" class="collapse">
<table class="table">
<thead>
<tr>
<th>
<input type="checkbox" id="select-all" />
<input type="checkbox" th:id="'select-all-' + ${entry.key.id}"/>
</th>
<th>File Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="file : ${files}">
<tr th:each="file : ${entry.value}">
<td>
<input type="checkbox" name="selectedFiles" th:value="${file.id}" />
<input type="checkbox" name="selectedFiles" th:value="${file.id}"/>
</td>
<td th:text="${file.fileName}"></td>
<td>
<a th:href="@{/files/download/{id}(id=${file.id})}" class="btn btn-primary">Download</a>
<a th:href="@{/files/delete/{id}(id=${file.id})}" class="btn btn-danger">Delete</a>
<a th:href="@{/files/download/{id}(id=${file.id})}" th:text="${file.fileName}"></a>
</td>
<td>
<a th:href="@{/files/delete/{id}(id=${file.id})}" class="btn btn-sm btn-outline-danger">Delete</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="d-flex justify-content-between mt-3">
<button type="button" class="btn btn-primary" onclick="downloadSelected()">Download Selected</button>
<button type="button" class="btn btn-danger" onclick="deleteSelected()">Delete Selected</button>
<button type="button" class="btn btn-sm btn-primary" onclick="downloadSelected()">Download Selected</button>
<button type="button" class="btn btn-sm btn-outline-danger" onclick="deleteSelected()">Delete Selected</button>
</div>
</form>
</section>
</main>
<footer class="bg-dark text-white text-center py-3">
<footer class="bg-primary text-white text-center py-3">
<p>&copy; 2024 Seshat App</p>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Select/Deselect all checkboxes
document.getElementById('select-all').addEventListener('change', function() {
const checkboxes = document.querySelectorAll('input[name="selectedFiles"]');
document.querySelectorAll('[id^=select-all]').forEach(function (element) {
element.addEventListener('change', function () {
const checkboxes = element.closest('table').querySelectorAll('input[name="selectedFiles"]');
checkboxes.forEach(checkbox => checkbox.checked = this.checked);
});
});
// Handle bulk download
function downloadSelected() {

View File

@ -1,40 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - Seshat App</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css">
<link rel="stylesheet" th:href="@{/css/styles.css}">
</head>
<body>
<header class="bg-primary text-white text-center py-3">
<div class="container d-flex justify-content-between align-items-center">
<h1 class="app-title mb-0">Seshat Audio Transcriber</h1>
</div>
</header>
<main class="container mt-4">
<h2>Login</h2>
<form th:action="@{/login}" method="post" class="mb-4">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" id="username" name="username" class="form-control" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" id="password" name="password" class="form-control" required>
</div>
<div class="d-flex justify-content-between">
<!-- Login Button -->
<button type="submit" class="btn btn-primary">Login</button>
<!-- Register Button -->
<a href="/register" class="btn btn-secondary ms-auto">Register</a>
</div>
</form>
</main>
<footer class="bg-dark text-white text-center py-3">
<p>&copy; 2024 Seshat App</p>
</footer>
</body>
</html>

View File

@ -1,38 +0,0 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register - Seshat App</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css">
<link rel="stylesheet" th:href="@{/css/styles.css}">
</head>
<body>
<header class="bg-primary text-white text-center py-3">
<div class="container d-flex justify-content-between align-items-center">
<h1 class="app-title mb-0">Seshat Audio Transcriber</h1>
</div>
</header>
<main class="container mt-4">
<h2>Register</h2>
<form th:action="@{/register}" method="post">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" id="username" name="username" class="form-control" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" id="email" name="email" class="form-control" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" id="password" name="password" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</main>
<footer class="bg-dark text-white text-center py-3">
<p>&copy; 2024 Seshat App</p>
</footer>
</body>
</html>