[recommendations-and-nl-search | WIP] create new page for category-to-item recs, create section in home page for author-to-item, add assets, add new dummy menu item

This commit is contained in:
Alex Martzios 2024-05-16 10:18:27 +03:00
parent cc19ee0437
commit 582285c8b2
19 changed files with 435 additions and 7 deletions

View File

@ -111,6 +111,10 @@ const routes: Routes = [
// redirectTo: ''
loadChildren: () => import('./searchPages/advanced/advancedSearchProjects.module').then(m => m.LibAdvancedSearchProjectsModule)
},
{
path: 'recommendations',
loadChildren: () => import('./recommendations/recommendations.module').then(m => m.RecommendationsModule)
},
{
path: 'reload',
loadChildren: () => import('./reload/libReload.module').then(m => m.LibReloadModule),

View File

@ -122,7 +122,8 @@ export class AppComponent {
null, null, "alpha-badge", null, "_blank", "internal", false,
[
new MenuItem("recommendations", "Community Recommendations", "https://test.darelab.athenarc.gr/crps/", "", false, [], null, {}),
new MenuItem("nl-search", "NL Search", "https://darelab.athenarc.gr/nl_search/fc4eosc", "", false, [], null, {})
new MenuItem("nl-search", "NL Search", "https://darelab.athenarc.gr/nl_search/fc4eosc", "", false, [], null, {}),
new MenuItem("category-to-item", "Dev - Category to Item", "", "/recommendations/category-to-item", false, [], null, {})
],
"Alpha"
)

View File

@ -16,6 +16,8 @@ import {HttpInterceptorService} from "./openaireLibrary/http-interceptor.service
import {ErrorInterceptorService} from "./openaireLibrary/error-interceptor.service";
import {DEFAULT_TIMEOUT, TimeoutInterceptor} from "./openaireLibrary/timeout-interceptor.service";
import {ConfigurationService} from "./openaireLibrary/utils/configuration/configuration.service";
import {RouteReuseStrategy} from '@angular/router';
import {CustomRouteReuseStrategy} from './openaireLibrary/shared/custom-route-reuse-strategy';
@NgModule({
imports: [
@ -34,6 +36,7 @@ import {ConfigurationService} from "./openaireLibrary/utils/configuration/config
exports: [AppComponent],
providers: [
ConfigurationService,
{provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy},
{provide: APP_ID, useValue: 'eosc'},
{
provide: HTTP_INTERCEPTORS,

View File

@ -73,4 +73,37 @@
</div>
</div>
<img src="/assets/home/cloud.svg" class="cloudSvg">
</div>
</div>
<div class="author-recommendations">
<!-- TODO: Add logic for logged in users -->
<div class="uk-section uk-container uk-container-large">
<hr class="uk-margin-large-bottom">
<ng-container *ngIf="!isLoggedIn">
<div class="uk-flex uk-flex-column uk-flex-middle uk-flex-center uk-padding uk-padding-remove-bottom uk-margin-small-bottom">
<span class="uk-h4 uk-text-center uk-width-1-2@m">
Login and receive recommendations based on your ORCID.
</span>
<a href="#" class="uk-button uk-button-primary uk-text-uppercase uk-margin-top">
Login
</a>
</div>
<div class="uk-text-right">
<img class="uk-margin-large-right" src="assets/recommendations/asset-3.svg" style="width: 225px;">
</div>
</ng-container>
<ng-container *ngIf="isLoggedIn">
<div class="uk-flex uk-flex-middle uk-flex-between uk-margin-medium-bottom">
<div class="uk-flex uk-flex-middle">
<icon [name]="'recommendations'" [flex]="true" [ratio]="1.5"></icon>
<span class="uk-text-bold uk-margin-left">Recommended for you</span>
</div>
<div>
<a href="#" class="uk-button uk-button-text uk-text-uppercase">
View more
</a>
</div>
</div>
</ng-container>
</div>
</div>

View File

@ -97,6 +97,9 @@ export class HomeComponent {
customFilter:SearchCustomFilter= null;
aggregator:AggregatorInfo;
// TODO: change this below with actual login functionality
isLoggedIn: boolean = false; // temp variable for testing HTML views!
constructor (
private route: ActivatedRoute,
private _router: Router,

View File

@ -24,7 +24,7 @@ import {EntitiesSelectionModule} from "../openaireLibrary/searchPages/searchUtil
import {QuickSelectionsModule} from "../openaireLibrary/searchPages/searchUtils/quick-selections.module";
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
import {IconsService} from "../openaireLibrary/utils/icons/icons.service";
import {book, cog, database, earth} from "../openaireLibrary/utils/icons/icons";
import {book, cog, database, earth, recommendations} from "../openaireLibrary/utils/icons/icons";
import {NumbersModule} from "../openaireLibrary/sharedComponents/numbers/numbers.module";
import {AdvancedSearchInputModule} from "../openaireLibrary/sharedComponents/advanced-search-input/advanced-search-input.module";
import {InputModule} from "../openaireLibrary/sharedComponents/input/input.module";
@ -55,6 +55,6 @@ import {SearchInputModule} from "../openaireLibrary/sharedComponents/search-inpu
})
export class HomeModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([book, earth, cog, database]);
this.iconsService.registerIcons([book, earth, cog, database, recommendations]);
}
}

@ -1 +1 @@
Subproject commit ca8b732a640cd222bc6a3a2792a98214dcd8e305
Subproject commit e80df9f3b0588f0f97fe1bfc211dc76e9850df81

View File

@ -0,0 +1,69 @@
<ng-container *ngIf="showLoading">
<div class="uk-container uk-container-large uk-section">
<loading></loading>
</div>
</ng-container>
<ng-container *ngIf="!showLoading && communities?.length">
<div class="uk-flex uk-background-default">
<aside [attr.offset]="offset" class="sidebar uk-background-default uk-visible@m" uk-sticky>
<div class="uk-padding">
<div class="uk-text-center">
<h5>In which community are you interested?</h5>
<p>Select a community to see recommendations.</p>
<div search-input [searchControl]="keywordControl"
[placeholder]="'Search for communities'"
[searchInputClass]="'flat background'">
</div>
</div>
<div class="uk-margin-medium-top">
<div *ngIf="filteredCommunities?.length">
<span class="uk-text-bold uk-text-meta uk-text-uppercase">Communities</span>
<ul class="uk-list uk-list-divider">
<li *ngFor="let community of filteredCommunities;" class="uk-padding-xsmall" [class.uk-active-custom]="activeCommunity == community.communityId">
<a class="uk-link-heading uk-text-bold" (click)="selectCommunity(community.communityId); setActiveCommunity(community.communityId);">
{{community.title}}
</a>
</li>
</ul>
</div>
<div *ngIf="filteredCommunities?.length == 0" class="uk-text-center uk-text-bold uk-text-meta">
No communities found based on your keyword
</div>
</div>
</div>
</aside>
<div class="content uk-width-expand uk-container">
<div *ngIf="!recommendations" class="uk-padding uk-position-center uk-text-center">
<h3 class="uk-width-1-1 uk-width-2-3@m uk-margin-auto">Select a community from the list on the left and receive recommendations.</h3>
</div>
<div *ngIf="recommendations?.length" class="uk-section">
<div *ngFor="let item of recommendations" class="uk-margin-large-bottom">
<div class="uk-flex uk-flex-middle uk-margin-medium-bottom">
<icon [name]="'recommendations'" [ratio]="1.5" [flex]="true"></icon>
<span class="uk-margin-left">Recommended by topic <span class="uk-text-bold">{{item.category}}</span></span>
</div>
<div class="uk-grid uk-child-width-1-3@m" uk-height-match=".uk-card" uk-grid>
<div *ngFor="let result of item.results | keyvalue;">
<a [routerLink]="properties.searchLinkToPublication.split('?')[0]" [queryParams]="{'pid': result.key}"
(click)="selectResult(item, result);" class="uk-link-reset">
<div class="uk-card uk-card-default uk-card-hover uk-text-xsmall uk-padding-small">
<ng-container *ngIf="result.value['title']">
<div class="multi-line-ellipsis lines-2">
<span class="uk-text-small uk-text-bold">{{result.value['title']}}</span>
</div>
<hr>
</ng-container>
<div *ngIf="result.value['publisher']" class="uk-text-truncate"><span class="uk-text-meta">Publisher:</span> {{result.value['publisher']}}</div>
<div *ngIf="result.value['publication_date']" class="uk-text-truncate"><span class="uk-text-meta">Date:</span> {{result.value['publication_date']}}</div>
<div *ngIf="result.value['country']" class="uk-text-truncate"><span class="uk-text-meta">Country:</span> {{result.value['country']}}</div>
<div *ngIf="result.value['authors']" class="uk-text-truncate"><span class="uk-text-meta">Authors:</span> {{result.value['authors']}}</div>
<div *ngIf="result.key" class="uk-text-truncate"><span class="uk-text-meta">DOI:</span> {{result.key}}</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-container>

View File

@ -0,0 +1,30 @@
@import (less) "~src/assets/openaire-theme/less/color.less";
@header-height: var(--header-height);
@sidebar-width: 464px;
.sidebar, .content {
position: relative;
}
.sidebar {
height: calc(100vh - @header-height);
width: @sidebar-width;
overflow-y: auto;
}
.content {
background-color: @default-color;
}
.uk-active-custom {
background-color: @ciel-color;
position: relative;
&::after {
position: absolute;
right: 0;
font-size: 1.8em;
font-family: "Material Icons";
content: "\e5cc"; /* chevron right */
}
}

View File

@ -0,0 +1,108 @@
import {Component} from "@angular/core";
import {CommunitiesService} from "../../openaireLibrary/connect/communities/communities.service";
import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties";
import {properties} from "../../../environments/environment";
import {CommunityInfo} from "../../openaireLibrary/connect/community/communityInfo";
import {Subscriber} from "rxjs";
import {FormBuilder, FormControl} from "@angular/forms";
import {debounceTime, distinctUntilChanged} from "rxjs/operators";
import {RecommendationsService} from "../recommendations.service";
import {ActivatedRoute, Router} from "@angular/router";
@Component({
selector: 'category-to-item',
templateUrl: './category-to-item.component.html',
styleUrls: ['category-to-item.component.less']
})
export class CategoryToItemComponent {
private subscriptions = [];
properties: EnvProperties = properties;
showLoading: boolean = true;
offset: number;
activeCommunity: string;
communities: CommunityInfo[];
filteredCommunities: CommunityInfo[];
recommendations: any;
allRecommendations: any;
keywordControl: FormControl;
keyword: string;
getRecommendationsForCommunityAPI: string = 'https://darelab.athenarc.gr/api/faircore/category-based-recommender/recommend';
giveFeedbackForRecommendation: string = 'https://darelab.athenarc.gr/api/faircore/category-based-recommender/update/';
constructor(private communitiesService: CommunitiesService,
private recommendationsService: RecommendationsService,
private router: Router,
private route: ActivatedRoute,
private fb: FormBuilder) {
}
ngOnInit() {
this.properties = properties;
if (typeof document !== "undefined") {
this.offset = Number.parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height'));
}
this.getCommunities();
this.subscriptions.push(this.route.params.subscribe(params => {
if(params && params['community']) {
this.subscriptions.push(this.recommendationsService.getRecommendationsForCommunity(this.getRecommendationsForCommunityAPI, params['community']).subscribe(data => {
this.recommendations = Object.keys(data['recommendations']).map(category => ({category, results: data['recommendations'][category]}));
this.setActiveCommunity(params['community']);
}));
}
}));
this.keywordControl = this.fb.control('');
this.subscriptions.push(this.keywordControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged()).subscribe(value => {
this.keyword = value;
this.filtering();
}));
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscriber) {
subscription.unsubscribe();
}
});
}
private getCommunities() {
this.subscriptions.push(this.communitiesService.getCommunities(this.properties, this.properties.communitiesAPI).subscribe(data => {
this.communities = data;
this.communities.sort((a, b) => a['title'].localeCompare(b['title']));
this.filteredCommunities = this.communities;
this.showLoading = false;
}));
}
filtering() {
let filteredCommunities = this.communities;
if(!this.keyword){
this.keyword = '';
}
if(this.communities.length) {
filteredCommunities = filteredCommunities.filter(item => (item['title'] && item['title'].toLowerCase().includes(this.keyword.toLowerCase())) || (item['shortTitle'] && item['shortTitle'].toLowerCase().includes(this.keyword.toLowerCase())));
}
this.filteredCommunities = filteredCommunities;
}
selectCommunity(id: string) {
this.router.navigate(['/recommendations/category-to-item/' + id]);
}
setActiveCommunity(id) {
this.activeCommunity = id;
}
selectResult(item, result) {
sessionStorage.setItem('previousPage', 'fc4eosc');
// TODO: check if feedback recommendation works
this.subscriptions.push(this.recommendationsService.giveFeedbackForRecommendation(this.giveFeedbackForRecommendation, 'enermaps', item.category, result.key).subscribe(data => {
console.log(data);
}));
}
}

View File

@ -0,0 +1,17 @@
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import {CategoryToItemComponent} from './category-to-item/category-to-item.component';
@NgModule({
imports: [
RouterModule.forChild([
{
path: 'category-to-item', component: CategoryToItemComponent,
},
{
path: 'category-to-item/:community', component: CategoryToItemComponent
}
])
]
})
export class RecommendationsRoutingModule { }

View File

@ -0,0 +1,32 @@
import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {RouterModule} from "@angular/router";
import {CategoryToItemComponent} from "./category-to-item/category-to-item.component";
import {RecommendationsRoutingModule} from "./recommendations-routing.module";
import {SearchInputModule} from "../openaireLibrary/sharedComponents/search-input/search-input.module";
import {CommunitiesService} from "../openaireLibrary/connect/communities/communities.service";
import {IconsModule} from "../openaireLibrary/utils/icons/icons.module";
import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module";
import {RecommendationsService} from "./recommendations.service";
@NgModule({
imports: [
RecommendationsRoutingModule, CommonModule, RouterModule, IconsModule,
SearchInputModule, LoadingModule
],
declarations: [
CategoryToItemComponent
],
providers: [
CommunitiesService, RecommendationsService
],
exports: [
CategoryToItemComponent
]
})
export class RecommendationsModule {
constructor() {
}
}

View File

@ -0,0 +1,55 @@
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {Injectable} from "@angular/core";
@Injectable()
export class RecommendationsService {
constructor(private http: HttpClient) {
}
getRecommendationsForCommunity(url: string, communityId: string) {
const body = {
// TODO: FIX THIS!
// "community": communityId,
"community": "enermaps",
};
const options = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
return this.http.post(url, body, options);
}
giveFeedbackForRecommendation(url: string, communityId: string, category: string, doi: string) {
const body = {
"category": category,
// TODO: FIX THIS!
// "community": communityId,
"community": "enermaps",
"publication": doi,
};
const options = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
return this.http.post(url, body, options);
}
getRecommendationsForPublication(url: string, communityId: string, id: string) {
const body = {
// TODO: FIX THIS!
// "community": communityId,
"community": "enermaps",
"id": id,
"num": 6
};
const options = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
return this.http.post(url, body, options);
}
}

@ -1 +1 @@
Subproject commit 651102a5ba049b71bed8eb6a85a8d02cefcb24cc
Subproject commit e48bf941bcdc567a3d09826b5686e70d43fafd46

View File

@ -168,6 +168,10 @@
z-index: -1;
}
.author-recommendations hr {
border-top: 1px solid @grey-color;
}
//.image-front-topbar, .search-form, #main-menu .uk-navbar-container, #main-menu-small .uk-navbar-container {
.eosc-explore-back-search-bar {
//background: @global-primary-background;

@ -1 +1 @@
Subproject commit 37639eab68c63a506b7df10c42e3379c4a05d94d
Subproject commit fe10d2e9195fdebf3d906f28abbb072f3617c4ee

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 165.67 142.95">
<defs>
<style>
.cls-1 {
stroke-width: 0px;
}
</style>
</defs>
<g id="Layer_1-2" data-name="Layer 1">
<g>
<path class="cls-1" d="m78.87,47.8c-7.25-.92-16.45,2.46-18.53,15-.18,1.09.55,2.12,1.64,2.3.11.02.22.03.33.03.96,0,1.81-.69,1.97-1.67,2.03-12.25,11.29-12.04,14.08-11.69.09.01.25.03.33.03,1.1,0,2-.9,2-2s-.8-1.91-1.82-2Zm0,0c-7.25-.92-16.45,2.46-18.53,15-.18,1.09.55,2.12,1.64,2.3.11.02.22.03.33.03.96,0,1.81-.69,1.97-1.67,2.03-12.25,11.29-12.04,14.08-11.69.09.01.25.03.33.03,1.1,0,2-.9,2-2s-.8-1.91-1.82-2Zm80.15,15.39c-41.4-21.33-39.11-30.98-48.51-46.48-6.71-11.06-11.35-14.09-13.45-14.92-.73-.29-1.42-.64-2.12-1-3.51-1.78-14.48-.06-17.77.52-.62.1-1.23.25-1.83.45-5.94,1.92-40.26,13.5-58.54,29.94C-3.27,49.73-.43,75.91,1.05,84.78c2.26,13.58,19.56,47.24,72.13,55.87,52.57,8.64,70.85-7.62,85.84-39.11,14.98-31.49,0-38.35,0-38.35Zm-116.89-15.36c-.06.13-9.43,5.27-9.43,5.27l3.91-10.92-7.43-7.68,11.04,1.14-.22-.03c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.64,1.21s-9.24,6.07-9.24,6.19c.19,0,2.31,11.84,2.31,11.84,0,0-8.63-7.88-8.82-7.88Zm37.27,68.26s-12.1-.57-12.38-.86c-.29-.29-4.67-2.19-5.34-6.95-.66-4.76,0-7.81,0-7.81l24.48,2.57s-.67,12.1-6.76,13.05Zm7.68-18.07c-1.51,2.02-24.37-2.22-24.37-2.22-.38-1.01-.64-5.39-2.42-9.2-1.78-3.81-15.11-17.4-3.68-35.05,11.42-17.65,31.81-9.91,31.81-9.91,0,0,18.03,7.24,16.88,22.99-1.14,15.74-7.42,19.67-9.2,21.33-.59.55-7.2,9.65-9.02,12.06Zm31.56,25.75s-8.62-7.87-8.83-7.87c-.06.12-9.43,5.27-9.43,5.27l3.91-10.92-7.43-7.69,11.05,1.15-.23-.03c.2-.26,4.86-10.16,4.86-10.16l2.38,11.01,10.64,1.21s-9.24,6.07-9.24,6.19c.19,0,2.32,11.84,2.32,11.84Zm13.58-33.14s-8.63-7.88-8.82-7.88c-.06.13-9.43,5.27-9.43,5.27l3.91-10.92-7.43-7.68,11.04,1.14-.22-.03c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.64,1.21s-9.24,6.07-9.24,6.19c.19,0,2.31,11.84,2.31,11.84Zm-53.35-42.83c-7.25-.92-16.45,2.46-18.53,15-.18,1.09.55,2.12,1.64,2.3.11.02.22.03.33.03.96,0,1.81-.69,1.97-1.67,2.03-12.25,11.29-12.04,14.08-11.69.09.01.25.03.33.03,1.1,0,2-.9,2-2s-.8-1.91-1.82-2Zm0,0c-7.25-.92-16.45,2.46-18.53,15-.18,1.09.55,2.12,1.64,2.3.11.02.22.03.33.03.96,0,1.81-.69,1.97-1.67,2.03-12.25,11.29-12.04,14.08-11.69.09.01.25.03.33.03,1.1,0,2-.9,2-2s-.8-1.91-1.82-2Zm0,0c-7.25-.92-16.45,2.46-18.53,15-.18,1.09.55,2.12,1.64,2.3.11.02.22.03.33.03.96,0,1.81-.69,1.97-1.67,2.03-12.25,11.29-12.04,14.08-11.69.09.01.25.03.33.03,1.1,0,2-.9,2-2s-.8-1.91-1.82-2Z"/>
<path class="cls-1" d="m80.69,49.8c0,1.1-.9,2-2,2-.08,0-.24-.02-.33-.03-2.79-.35-12.05-.56-14.08,11.69-.16.98-1.01,1.67-1.97,1.67-.11,0-.22-.01-.33-.03-1.09-.18-1.82-1.21-1.64-2.3,2.08-12.54,11.28-15.92,18.53-15,1.02.09,1.82.95,1.82,2Z"/>
<path class="cls-1" d="m80.69,49.8c0,1.1-.9,2-2,2-.08,0-.24-.02-.33-.03-2.79-.35-12.05-.56-14.08,11.69-.16.98-1.01,1.67-1.97,1.67-.11,0-.22-.01-.33-.03-1.09-.18-1.82-1.21-1.64-2.3,2.08-12.54,11.28-15.92,18.53-15,1.02.09,1.82.95,1.82,2Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 109.97 98.32">
<defs>
<style>
.cls-1 {
stroke-width: 0px;
}
</style>
</defs>
<g id="Layer_1-2" data-name="Layer 1">
<g>
<path class="cls-1" d="m10.83,10.16c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.63,1.21s-9.43,6.19-9.24,6.19,2.32,11.84,2.32,11.84c0,0-8.76-8-8.83-7.87s-9.43,5.27-9.43,5.27l3.9-10.92L0,9.05l11.05,1.14-.22-.03Z"/>
<path class="cls-1" d="m92.1,45.08c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.63,1.21s-9.43,6.19-9.24,6.19,2.32,11.84,2.32,11.84c0,0-8.76-8-8.83-7.87s-9.43,5.27-9.43,5.27l3.9-10.92-7.43-7.68,11.05,1.14-.22-.03Z"/>
<path class="cls-1" d="m78.51,78.22c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.63,1.21s-9.43,6.19-9.24,6.19,2.32,11.84,2.32,11.84c0,0-8.76-8-8.83-7.87s-9.43,5.27-9.43,5.27l3.9-10.92-7.43-7.68,11.05,1.14-.22-.03Z"/>
<path class="cls-1" d="m32.51,75.02l24.48,2.57s-.67,12.1-6.76,13.05c0,0-12.1-.57-12.38-.86s-4.67-2.19-5.33-6.95,0-7.81,0-7.81Z"/>
<path class="cls-1" d="m59.24,16.19s-20.38-7.74-31.81,9.91c-11.43,17.65,1.91,31.23,3.69,35.04,1.77,3.81,2.03,8.19,2.42,9.21,0,0,22.85,4.24,24.37,2.22,1.81-2.41,8.43-11.51,9.01-12.06,1.78-1.66,8.07-5.59,9.21-21.33,1.14-15.75-16.89-22.99-16.89-22.99Zm-9.72,10.15c-.09,0-.25-.01-.33-.02-2.79-.35-12.05-.56-14.08,11.69-.16.97-1.01,1.67-1.97,1.67-.11,0-.22-.01-.33-.03-1.09-.18-1.83-1.21-1.65-2.3,2.09-12.54,11.29-15.92,18.53-15,1.03.09,1.83.95,1.83,1.99,0,1.11-.9,2-2,2Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 165.67 142.94">
<defs>
<style>
.cls-1 {
fill: #ffd215;
}
.cls-1, .cls-2, .cls-3 {
stroke-width: 0px;
}
.cls-2 {
fill: #e86438;
}
.cls-3 {
fill: #f9f9f9;
}
</style>
</defs>
<g id="Layer_1-2" data-name="Layer 1">
<g>
<path class="cls-2" d="m94.93.79c.7.35,1.39.71,2.12.99,2.1.83,6.74,3.86,13.45,14.93,9.4,15.49,7.11,25.14,48.51,46.48,0,0,14.98,6.86,0,38.35s-33.27,47.75-85.84,39.11C20.6,132.01,3.31,98.35,1.04,84.77c-1.48-8.86-4.32-35.05,15.75-53.08C35.08,15.26,69.4,3.67,75.33,1.75c.6-.19,1.21-.34,1.83-.45,3.29-.57,14.26-2.29,17.77-.51Z"/>
<path class="cls-1" d="m40,35.6c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.63,1.21s-9.43,6.19-9.24,6.19,2.32,11.84,2.32,11.84c0,0-8.76-8-8.83-7.87s-9.43,5.27-9.43,5.27l3.9-10.92-7.43-7.68,11.05,1.14"/>
<path class="cls-1" d="m121.27,70.52c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.63,1.21s-9.43,6.19-9.24,6.19,2.32,11.84,2.32,11.84c0,0-8.76-8-8.83-7.87s-9.43,5.27-9.43,5.27l3.9-10.92-7.43-7.68,11.05,1.14"/>
<path class="cls-1" d="m107.68,103.67c.19-.25,4.86-10.16,4.86-10.16l2.38,11.02,10.63,1.21s-9.43,6.19-9.24,6.19,2.32,11.84,2.32,11.84c0,0-8.76-8-8.83-7.87s-9.43,5.27-9.43,5.27l3.9-10.92-7.43-7.68,11.05,1.14"/>
<path class="cls-3" d="m61.68,100.46l24.48,2.57s-.67,12.1-6.76,13.05c0,0-12.1-.57-12.38-.86s-4.67-2.19-5.33-6.95,0-7.81,0-7.81Z"/>
<path class="cls-3" d="m62.7,95.79c-.38-1.02-.64-5.4-2.42-9.21s-15.11-17.4-3.68-35.05,31.81-9.9,31.81-9.9c0,0,18.03,7.24,16.89,22.98s-7.43,19.67-9.21,21.33c-.59.55-7.2,9.65-9.02,12.06-1.52,2.02-24.37-2.22-24.37-2.22Z"/>
<path class="cls-2" d="m62.3,65.12c-.11,0-.22,0-.33-.03-1.09-.18-1.83-1.21-1.65-2.3,2.08-12.55,11.28-15.92,18.53-15h0c1.02.09,1.82.95,1.82,1.99,0,1.1-.9,2-2,2-.08,0-.24-.01-.33-.02-2.79-.35-12.05-.56-14.08,11.69-.16.98-1.01,1.67-1.97,1.67Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB