Merge pull request #1227 from dpalou/MOBILE-2310

Mobile 2310
main
Juan Leyva 2018-01-24 09:41:47 +01:00 committed by GitHub
commit 80e783f911
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
146 changed files with 11405 additions and 733 deletions

View File

@ -27,7 +27,7 @@
<p><core-format-text [text]="courseName"></core-format-text></p>
</ion-item>
<ion-item text-wrap *ngIf="event.moduleIcon">
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start> {{event.moduleName}}
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start alt="" role="presentation" class="core-module-icon"> {{event.moduleName}}
</ion-item>
<ion-item>
<p text-wrap *ngIf="event.description">

View File

@ -21,7 +21,7 @@ import { CoreCoursesProvider } from '../../../../core/courses/providers/courses'
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreLocalNotificationsProvider } from '../../../../providers/local-notifications';
//import { CoreCourseProvider } from '../../../core/course/providers/course';
import { CoreCourseProvider } from '../../../../core/course/providers/course';
import * as moment from 'moment';
/**
@ -48,7 +48,7 @@ export class AddonCalendarEventPage {
constructor(private translate: TranslateService, private calendarProvider: AddonCalendarProvider, private navParams: NavParams,
private domUtils: CoreDomUtilsProvider, private coursesProvider: CoreCoursesProvider,
private calendarHelper: AddonCalendarHelperProvider, private sitesProvider: CoreSitesProvider,
private localNotificationsProvider: CoreLocalNotificationsProvider/*, private courseProvider: CoreCourseProvider*/) {
private localNotificationsProvider: CoreLocalNotificationsProvider, private courseProvider: CoreCourseProvider) {
this.eventId = navParams.get('id');
this.notificationsEnabled = localNotificationsProvider.isAvailable();
@ -95,8 +95,8 @@ export class AddonCalendarEventPage {
// Guess event title.
let title = this.translate.instant('addon.calendar.type' + event.eventtype);
if (event.moduleIcon) {
// @todo: It's a module event, translate the module name to the current language.
let name = "" //this.courseProvider.translateModuleName(event.modulename);
// It's a module event, translate the module name to the current language.
let name = this.courseProvider.translateModuleName(event.modulename);
if (name.indexOf('core.mod_') === -1) {
event.moduleName = name;
}

View File

@ -22,7 +22,7 @@
<ion-list *ngIf="filteredEvents && filteredEvents.length">
<a ion-item text-wrap *ngFor="let event of filteredEvents" [title]="event.name" (click)="gotoEvent(event.id)" [class.core-split-item-selected]="event.id == eventId">
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start>
<img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" item-start class="core-module-icon">
<ion-icon *ngIf="!event.moduleIcon" name="{{event.icon}}" item-start></ion-icon>
<h2><core-format-text [text]="event.name"></core-format-text></h2>
<p>{{ event.timestart | coreToLocaleString }}</p>

View File

@ -230,8 +230,8 @@ export class AddonCalendarProvider {
return this.groupsProvider.getUserGroups(courses, siteId).then((groups) => {
let now = this.timeUtils.timestamp(),
start = now + (CoreConstants.secondsDay * daysToStart),
end = start + (CoreConstants.secondsDay * daysInterval);
start = now + (CoreConstants.SECONDS_DAY * daysToStart),
end = start + (CoreConstants.SECONDS_DAY * daysInterval);
// The core_calendar_get_calendar_events needs all the current user courses and groups.
let data = {

View File

@ -15,7 +15,7 @@
import { Injectable } from '@angular/core';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSitesProvider } from '../../../providers/sites';
//import { CoreCourseProvider } from '../../../core/course/providers/course';
import { CoreCourseProvider } from '../../../core/course/providers/course';
/**
* Service that provides some features regarding lists of courses and categories.
@ -32,7 +32,7 @@ export class AddonCalendarHelperProvider {
'category': 'albums'
};
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider/*, private courseProvider: CoreCourseProvider*/) {
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider) {
this.logger = logger.getInstance('AddonCalendarHelperProvider');
}
@ -44,8 +44,7 @@ export class AddonCalendarHelperProvider {
formatEventData(e: any) {
e.icon = this.EVENTICONS[e.eventtype] || false;
if (!e.icon) {
// @todo: It's a module event.
//e.icon = this.courseProvider.getModuleIconSrc(e.modulename);
e.icon = this.courseProvider.getModuleIconSrc(e.modulename);
e.moduleIcon = e.icon;
}
};

View File

@ -12,18 +12,6 @@
height: calc(100% - #{($card-ios-margin-end + $card-ios-margin-start)});
}
// Top tabs
// -------------------------
.ios .core-top-tabbar {
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
> a {
font-size: 1.6rem;
}
}
.bar-buttons core-context-menu .button-clear-ios {
color: $toolbar-ios-button-color;
}

View File

@ -48,6 +48,7 @@ import { CoreFilepoolProvider } from '../providers/filepool';
import { CoreUpdateManagerProvider } from '../providers/update-manager';
import { CorePluginFileDelegate } from '../providers/plugin-file-delegate';
// Core modules.
import { CoreComponentsModule } from '../components/components.module';
import { CoreEmulatorModule } from '../core/emulator/emulator.module';
import { CoreLoginModule } from '../core/login/login.module';
@ -55,6 +56,9 @@ import { CoreMainMenuModule } from '../core/mainmenu/mainmenu.module';
import { CoreCoursesModule } from '../core/courses/courses.module';
import { CoreFileUploaderModule } from '../core/fileuploader/fileuploader.module';
import { CoreSharedFilesModule } from '../core/sharedfiles/sharedfiles.module';
import { CoreCourseModule } from '../core/course/course.module';
// Addon modules.
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
// For translate loader. AoT requires an exported function for factories.
@ -80,13 +84,14 @@ export function createTranslateLoader(http: HttpClient) {
deps: [HttpClient]
}
}),
CoreComponentsModule,
CoreEmulatorModule,
CoreLoginModule,
CoreMainMenuModule,
CoreCoursesModule,
CoreFileUploaderModule,
CoreSharedFilesModule,
CoreComponentsModule,
CoreCourseModule,
AddonCalendarModule
],
bootstrap: [IonicApp],

View File

@ -31,6 +31,9 @@
}
}
.opacity-hide { opacity: 0; }
.core-big { font-size: 115%; }
@media only screen and (min-width: 430px) {
.core-center-view .scroll-content {
display: flex!important;
@ -63,6 +66,10 @@
margin: 0;
}
.item-dimmed {
opacity: 0.6;
}
.core-oauth-icon, .item.core-oauth-icon, .list .item.core-oauth-icon {
min-height: 32px;
img, .label {
@ -82,6 +89,20 @@
font-weight: bold;
}
.core-module-icon {
width: auto;
}
.core-button-spinner {
min-height: 44px;
min-width: 50px;
text-align: center;
.spinner {
margin-top: 8px;
}
}
// Avatar
// -------------------------
// Large centered avatar
@ -133,7 +154,8 @@ ion-avatar ion-img, ion-avatar img {
}
/** Format Text */
core-format-text[maxHeight], *[core-format-text][maxHeight] {
core-format-text[maxHeight], *[core-format-text][maxHeight],
core-format-text[ng-reflect-max-height], *[core-format-text][ng-reflect-max-height] {
display: block;
position: relative;
width: 100%;
@ -148,6 +170,7 @@ core-format-text[maxHeight], *[core-format-text][maxHeight] {
// This is to allow clicks in radio/checkbox content.
&.core-text-formatted {
cursor: pointer;
pointer-events: auto;
.core-show-more {
display: none;
@ -173,19 +196,6 @@ core-format-text[maxHeight], *[core-format-text][maxHeight] {
z-index: 1001;
background-color: $white;
padding-left: 10px;
/* @todo
&:after {
@extend .ion;
content: $ionicon-var-chevron-down;
margin-left: 10px;
color: $item-icon-accessory-color;
}
*/
}
&.core-expand-in-fullview .core-show-more:after {
// content: $ionicon-var-chevron-right; @todo
}
&:before {
@ -205,6 +215,49 @@ core-format-text[maxHeight], *[core-format-text][maxHeight] {
}
}
}
&.core-expand-in-fullview {
.core-show-more {
@include svg-background-image($item-md-detail-push-svg, true);
@include padding-horizontal(null, 18px);
@include background-position(end, 0, center);
background-repeat: no-repeat;
background-size: 14px 14px;
}
}
}
.core-media-adapt-width {
max-width: 100%;
}
audio.core-media-adapt-width {
width: 100%;
}
.core-adapted-img-container {
position: relative;
display: inline-block;
}
.core-image-viewer-icon {
position: absolute;
right: 10px;
bottom: 10px;
color: $black;
border-radius: 5px;
background: rgba(255, 255, 255, .5);
text-align: center;
width: 32px;
height: 32px;
max-width: 32px;
line-height: 32px;
font-size: 24px;
ion-icon {
font-size: 24px;
}
}
core-format-text, *[core-format-text] {
@ -226,6 +279,21 @@ core-format-text, *[core-format-text] {
.badge {
position: initial !important;
}
// Images in ion-card have width 100% and display block. Remove that when the image is in core-format-text.
img {
width: initial;
display: inline;
}
.core-disable-media-adapt,
.core-disable-media-adapt .core-media-adapt-width {
max-width: none !important;
max-height: none !important;
width: initial !important;
height: initial !important;
display: inline-block !important;
}
}
// Message item.
@ -249,32 +317,6 @@ ion-select {
position: relative
}
// Top tabs
// -------------------------
.core-top-tabbar {
@include position(null, null, 0, 0);
z-index: $z-index-toolbar;
display: flex;
width: 100%;
background: $core-top-tabs-background;
> a {
@extend .tab-button;
background: $core-top-tabs-background;
color: $core-top-tabs-color !important;
border-bottom: 1px solid $core-top-tabs-border;
font-size: 1.6rem;
&[aria-selected=true] {
color: $core-top-tabs-color-active !important;
border-bottom: 2px solid $core-top-tabs-color-active;
}
}
}
// File uploader.
// -------------------------
@ -293,3 +335,76 @@ ion-select {
cursor: pointer;
}
}
// Atto styles
// -------------------------
.atto_image_preview {
width: 100%;
height: 100%;
margin-left: auto;
margin-right: auto;
}
.atto_image_preview_box {
max-height: 200px;
margin-bottom: 1em;
overflow: auto;
}
.editor_atto_content img {
cursor: pointer;
}
.atto_image_size {
display: inline-block;
}
.atto_image_size input[type=checkbox] {
margin-left: 1em;
margin-right: 1em;
}
.atto_image_size input[type=text] {
width: 3em;
}
.atto_image_size label {
display: inline-block;
}
.atto_image_button_text-top {
vertical-align: text-top;
margin: 0 0.5em;
}
.atto_image_button_middle {
vertical-align: middle;
margin: 0 0.5em;
}
.atto_image_button_text-bottom {
vertical-align: text-bottom;
margin: 0 0.5em;
}
.atto_image_button_text-top.img-responsive,
.atto_image_button_middle.img-responsive,
.atto_image_button_text-bottom.img-responsive {
/* If the image is display: block then linking the image to URLs won't work. */
display: inline-block;
max-width: calc(100% - 1em);
}
/*rtl:begin:ignore*/
.atto_image_button_left {
float: left;
margin: 0 0.5em 0 0;
max-width: calc(100% - 1em);
}
.atto_image_button_right {
float: right;
margin: 0 0 0 0.5em;
max-width: calc(100% - 1em);
}
/*rtl:end:ignore*/

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<path style="fill:#999999;" d="M10,0v2H6V0H10z M11,2h1c1.1,0,2,0.9,2,2v1h2V2c0-1.1-0.9-2-2-2h-3V2z M16,6h-2v4h2V6z M14,11v1
c0,1.1-0.9,2-2,2h-1v2h3c1.1,0,2-0.9,2-2v-3H14z M10,16v-2H6v2H10z M5,14H4c-1.1,0-2-0.9-2-2v-1H0v3c0,1.1,0.9,2,2,2h3V14z M0,10h2
V6H0V10z M2,5V4c0-1.1,0.9-2,2-2h1V0H2C0.9,0,0,0.9,0,2v3H2z"/>
<path style="fill:#FF403C;" d="M10.2,8l2.6-2.6c0.4-0.4,0.4-1,0-1.4L12,3.3c-0.4-0.4-1-0.4-1.4,0L8,5.9L5.4,3.3
c-0.4-0.4-1-0.4-1.4,0L3.3,4c-0.4,0.4-0.4,1,0,1.4L5.9,8l-2.6,2.6C3,11,3,11.6,3.3,12l0.7,0.7c0.4,0.4,1,0.4,1.4,0L8,10.2l2.5,2.5
c0.4,0.4,1,0.4,1.4,0l0.7-0.7c0.4-0.4,0.4-1,0-1.4L10.2,8z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M10 0v2H6V0h4zm1 2h1c1.1 0 2 .9 2 2v1h2V2c0-1.1-.9-2-2-2h-3v2zm5 4h-2v4h2V6zm-2 5v1c0 1.1-.9 2-2 2h-1v2h3c1.1 0 2-.9 2-2v-3h-2zm-4 5v-2H6v2h4zm-5-2H4c-1.1 0-2-.9-2-2v-1H0v3c0 1.1.9 2 2 2h3v-2zm-5-4h2V6H0v4zm2-5V4c0-1.1.9-2 2-2h1V0H2C.9 0 0 .9 0 2v3h2z" fill="#FF2727"/></svg>

After

Width:  |  Height:  |  Size: 579 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<path style="fill:#999999;" d="M10,0v2H6V0H10z M11,2h1c1.1,0,2,0.9,2,2v1h2V2c0-1.1-0.9-2-2-2h-3V2z M16,6h-2v4h2V6z M14,11v1
c0,1.1-0.9,2-2,2h-1v2h3c1.1,0,2-0.9,2-2v-3H14z M10,16v-2H6v2H10z M5,14H4c-1.1,0-2-0.9-2-2v-1H0v3c0,1.1,0.9,2,2,2h3V14z M0,10h2
V6H0V10z M2,5V4c0-1.1,0.9-2,2-2h1V0H2C0.9,0,0,0.9,0,2v3H2z"/>
</svg>

After

Width:  |  Height:  |  Size: 955 B

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<path style="fill:#999999;" d="M10,0v2H6V0H10z M11,2h1c0.4,0,0.8,0.1,1.1,0.3c0.3-0.3,0.8-0.4,1.2-0.4c0.5,0,1,0.2,1.4,0.6L16,2.8
V2c0-1.1-0.9-2-2-2h-3V2z M14,10h2V6.4l-2,2V10z M14,11v1c0,1.1-0.9,2-2,2h-1v2h3c1.1,0,2-0.9,2-2v-3H14z M10,16v-2H6v2H10z M5,14H4
c-1.1,0-2-0.9-2-2v-1H0v3c0,1.1,0.9,2,2,2h3V14z M0,10h2V6H0V10z M2,5V4c0-1.1,0.9-2,2-2h1V0H2C0.9,0,0,0.9,0,2v3H2z"/>
<path style="fill:#99CC33;" d="M15.7,3.9L15,3.2c-0.4-0.4-1-0.4-1.4,0l-6,6L5.4,7C5,6.7,4.4,6.7,4,7L3.3,7.7c-0.4,0.4-0.4,1,0,1.4
l3.6,3.6c0.4,0.4,1,0.4,1.4,0l7.4-7.4C16.1,4.9,16.1,4.3,15.7,3.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M10 0v2H6V0h4zm1 2h1c.4 0 .8.1 1.1.3.3-.3.8-.4 1.2-.4.5 0 1 .2 1.4.6l.3.3V2c0-1.1-.9-2-2-2h-3v2zm3 8h2V6.4l-2 2V10zm0 1v1c0 1.1-.9 2-2 2h-1v2h3c1.1 0 2-.9 2-2v-3h-2zm-4 5v-2H6v2h4zm-5-2H4c-1.1 0-2-.9-2-2v-1H0v3c0 1.1.9 2 2 2h3v-2zm-5-4h2V6H0v4zm2-5V4c0-1.1.9-2 2-2h1V0H2C.9 0 0 .9 0 2v3h2z" fill="#FF2727"/><path d="M15.7 3.9l-.7-.7c-.4-.4-1-.4-1.4 0l-6 6L5.4 7c-.4-.3-1-.3-1.4 0l-.7.7c-.4.4-.4 1 0 1.4l3.6 3.6c.4.4 1 .4 1.4 0l7.4-7.4c.4-.4.4-1 0-1.4z" fill="#76A1F0"/></svg>

After

Width:  |  Height:  |  Size: 779 B

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<path style="fill:#999999;" d="M10,0v2H6V0H10z M11,2h1c0.4,0,0.8,0.1,1.1,0.3c0.3-0.3,0.8-0.4,1.2-0.4c0.5,0,1,0.2,1.4,0.6L16,2.8
V2c0-1.1-0.9-2-2-2h-3V2z M14,10h2V6.4l-2,2V10z M14,11v1c0,1.1-0.9,2-2,2h-1v2h3c1.1,0,2-0.9,2-2v-3H14z M10,16v-2H6v2H10z M5,14H4
c-1.1,0-2-0.9-2-2v-1H0v3c0,1.1,0.9,2,2,2h3V14z M0,10h2V6H0V10z M2,5V4c0-1.1,0.9-2,2-2h1V0H2C0.9,0,0,0.9,0,2v3H2z"/>
<path style="fill:#76A1F0;" d="M15.7,3.9L15,3.2c-0.4-0.4-1-0.4-1.4,0l-6,6L5.4,7C5,6.7,4.4,6.7,4,7L3.3,7.7c-0.4,0.4-0.4,1,0,1.4
l3.6,3.6c0.4,0.4,1,0.4,1.4,0l7.4-7.4C16.1,4.9,16.1,4.3,15.7,3.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M14 0H2C.9 0 0 .9 0 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V2c0-1.1-.9-2-2-2zm0 12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h8c1.1 0 2 .9 2 2v8z" fill="#FF2727"/></svg>

After

Width:  |  Height:  |  Size: 476 B

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<path style="fill:#999999;" d="M14,0H2C0.9,0,0,0.9,0,2v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V2C16,0.9,15.1,0,14,0z M14,12
c0,1.1-0.9,2-2,2H4c-1.1,0-2-0.9-2-2V4c0-1.1,0.9-2,2-2h8c1.1,0,2,0.9,2,2V12z"/>
</svg>

After

Width:  |  Height:  |  Size: 841 B

View File

@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M14 8.4V12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h8c.4 0 .8.1 1.1.3.3-.3.8-.4 1.2-.4.5 0 1 .2 1.4.6l.3.3V2c0-1.1-.9-2-2-2H2C.9 0 0 .9 0 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6.4l-2 2z" fill="#FF2727"/><path d="M15.7 3.9l-.7-.7c-.4-.4-1-.4-1.4 0l-6 6L5.4 7c-.4-.3-1-.3-1.4 0l-.7.7c-.4.4-.4 1 0 1.4l3.6 3.6c.4.4 1 .4 1.4 0l7.4-7.4c.4-.4.4-1 0-1.4z" fill="#76A1F0"/></svg>

After

Width:  |  Height:  |  Size: 682 B

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="overflow:visible;enable-background:new 0 0 16 16;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<path style="fill:#999999;" d="M14,8.4V12c0,1.1-0.9,2-2,2H4c-1.1,0-2-0.9-2-2V4c0-1.1,0.9-2,2-2h8c0.4,0,0.8,0.1,1.1,0.3
c0.3-0.3,0.8-0.4,1.2-0.4c0.5,0,1,0.2,1.4,0.6L16,2.8V2c0-1.1-0.9-2-2-2H2C0.9,0,0,0.9,0,2v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2
V6.4L14,8.4z"/>
<path style="fill:#76A1F0;" d="M15.7,3.9L15,3.2c-0.4-0.4-1-0.4-1.4,0l-6,6L5.4,7C5,6.7,4.4,6.7,4,7L3.3,7.7c-0.4,0.4-0.4,1,0,1.4
l3.6,3.6c0.4,0.4,1,0.4,1.4,0l7.4-7.4C16.1,4.9,16.1,4.3,15.7,3.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="14.0054" y1="0" x2="14.0054" y2="20.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);" points="16.3,0 15.4,0 6.7,0 6,0 6,20 6.7,20 21.7,20 22,20 22,6.6 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="14.0054" y1="1" x2="14.0054" y2="19.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="7,19 7,1 15.8,1 21,6.9 21,19 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="14.0054" y1="2" x2="14.0054" y2="18.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="8,18 8,2 15.4,2 20,7.3 20,18 "/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="18.3101" y1="0" x2="18.3101" y2="7.7852">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M14.8,7.5c0,0,5.2-1.3,7.2,0.3c0-0.1,0-1.2,0-1.2L16.2,0c0,0-1.5,0-1.6,0
C16.8,3,14.8,7.5,14.8,7.5z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="16.3003" y1="6.1616" x2="18.5911" y2="3.8708">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="0.5181" style="stop-color:#E5F3FC"/>
<stop offset="0.7045" style="stop-color:#DEF0FB"/>
<stop offset="0.8371" style="stop-color:#D3EBFA"/>
<stop offset="0.872" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BDD8F0"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.87" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.872" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BDD8F0"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M16.3,6.2c0.3-1.2,0.5-2.9,0.1-4.4l4,4.4C20,6.1,19.4,6,18.8,6C17.9,6,17,6.1,16.3,6.2z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="11.9673" y1="12.167" x2="11.9673" y2="23.8853">
<stop offset="0" style="stop-color:#DDA976"/>
<stop offset="1" style="stop-color:#9F6B37"/>
<a:midPointStop offset="0" style="stop-color:#DDA976"/>
<a:midPointStop offset="0.5" style="stop-color:#DDA976"/>
<a:midPointStop offset="1" style="stop-color:#9F6B37"/>
</linearGradient>
<path style="fill:url(#SVGID_6_);" d="M10,18.9c-0.3-2.2,9.4,0.5,9.3-1.4c0-0.8-8.4-3.4-11.4-4.1c-0.9-0.2-6.5-1.2-6.5-1.2
c-0.2,0.1-1.3,3.3-1.4,5.2c0.5,0.3,7.3,6.7,10,6.5c2.7-0.2,14.2-3.6,13.9-4.7C23.3,17.1,10.3,21.3,10,18.9z"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="11.4893" y1="13.2803" x2="11.4893" y2="22.9336">
<stop offset="0" style="stop-color:#FFDDAA"/>
<stop offset="1" style="stop-color:#E3B17E"/>
<a:midPointStop offset="0" style="stop-color:#FFDDAA"/>
<a:midPointStop offset="0.5" style="stop-color:#FFDDAA"/>
<a:midPointStop offset="1" style="stop-color:#E3B17E"/>
</linearGradient>
<path style="fill:url(#SVGID_7_);" d="M1.7,17.4C1.4,17.2,1.2,17,1,16.9c0.1-1.2,0.6-2.8,0.9-3.6c1.8,0.3,5.1,0.9,5.7,1
c2.6,0.6,9.4,2.3,9.7,3c0.5,1.1-8.3-1.9-8.1,1.7c0.2,3.5,12.4-0.6,12.7,0.5c0.2,0.7-10.1,3.6-12,3.5C7.9,22.8,3.3,18.8,1.7,17.4z"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="7.5928" y1="14.4141" x2="7.5928" y2="21.9336">
<stop offset="0" style="stop-color:#F1C592"/>
<stop offset="1" style="stop-color:#E1AF7C"/>
<a:midPointStop offset="0" style="stop-color:#F1C592"/>
<a:midPointStop offset="0.5" style="stop-color:#F1C592"/>
<a:midPointStop offset="1" style="stop-color:#E1AF7C"/>
</linearGradient>
<path style="fill:url(#SVGID_8_);" d="M10.1,21.9c-0.8-0.1-2.8-1-7.6-5.2l-0.3-0.3c0.1-0.7,0.3-1.4,0.5-2.1c2.1,0.4,4.3,0.8,4.7,0.9
c1.5,0.4,2.7,0.7,3.8,0.9c-1,0.1-1.8,0.4-2.3,1c-0.3,0.3-0.7,0.9-0.6,1.9c0.1,1.1,0.8,2.4,4,2.4c0.3,0,0.6,0,0.9,0
C11.8,21.7,10.7,21.9,10.1,21.9L10.1,21.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="14.0054" y1="0" x2="14.0054" y2="20.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);" points="16.3,0 15.4,0 6.7,0 6,0 6,20 6.7,20 21.7,20 22,20 22,6.6 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="14.0054" y1="1" x2="14.0054" y2="19.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="7,19 7,1 15.8,1 21,6.9 21,19 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="14.0054" y1="2" x2="14.0054" y2="18.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="8,18 8,2 15.4,2 20,7.3 20,18 "/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="18.3101" y1="0" x2="18.3101" y2="7.7852">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M14.8,7.5c0,0,5.2-1.3,7.2,0.3c0-0.1,0-1.2,0-1.2L16.2,0c0,0-1.5,0-1.6,0
C16.8,3,14.8,7.5,14.8,7.5z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="16.3003" y1="6.1616" x2="18.5911" y2="3.8708">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="0.5181" style="stop-color:#E5F3FC"/>
<stop offset="0.7045" style="stop-color:#DEF0FB"/>
<stop offset="0.8371" style="stop-color:#D3EBFA"/>
<stop offset="0.872" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BDD8F0"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.87" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.872" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BDD8F0"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M16.3,6.2c0.3-1.2,0.5-2.9,0.1-4.4l4,4.4C20,6.1,19.4,6,18.8,6C17.9,6,17,6.1,16.3,6.2z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="11.9673" y1="12.167" x2="11.9673" y2="23.8853">
<stop offset="0" style="stop-color:#DDA976"/>
<stop offset="1" style="stop-color:#9F6B37"/>
<a:midPointStop offset="0" style="stop-color:#DDA976"/>
<a:midPointStop offset="0.5" style="stop-color:#DDA976"/>
<a:midPointStop offset="1" style="stop-color:#9F6B37"/>
</linearGradient>
<path style="fill:url(#SVGID_6_);" d="M10,18.9c-0.3-2.2,9.4,0.5,9.3-1.4c0-0.8-8.4-3.4-11.4-4.1c-0.9-0.2-6.5-1.2-6.5-1.2
c-0.2,0.1-1.3,3.3-1.4,5.2c0.5,0.3,7.3,6.7,10,6.5c2.7-0.2,14.2-3.6,13.9-4.7C23.3,17.1,10.3,21.3,10,18.9z"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="11.4893" y1="13.2803" x2="11.4893" y2="22.9336">
<stop offset="0" style="stop-color:#FFDDAA"/>
<stop offset="1" style="stop-color:#E3B17E"/>
<a:midPointStop offset="0" style="stop-color:#FFDDAA"/>
<a:midPointStop offset="0.5" style="stop-color:#FFDDAA"/>
<a:midPointStop offset="1" style="stop-color:#E3B17E"/>
</linearGradient>
<path style="fill:url(#SVGID_7_);" d="M1.7,17.4C1.4,17.2,1.2,17,1,16.9c0.1-1.2,0.6-2.8,0.9-3.6c1.8,0.3,5.1,0.9,5.7,1
c2.6,0.6,9.4,2.3,9.7,3c0.5,1.1-8.3-1.9-8.1,1.7c0.2,3.5,12.4-0.6,12.7,0.5c0.2,0.7-10.1,3.6-12,3.5C7.9,22.8,3.3,18.8,1.7,17.4z"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="7.5928" y1="14.4141" x2="7.5928" y2="21.9336">
<stop offset="0" style="stop-color:#F1C592"/>
<stop offset="1" style="stop-color:#E1AF7C"/>
<a:midPointStop offset="0" style="stop-color:#F1C592"/>
<a:midPointStop offset="0.5" style="stop-color:#F1C592"/>
<a:midPointStop offset="1" style="stop-color:#E1AF7C"/>
</linearGradient>
<path style="fill:url(#SVGID_8_);" d="M10.1,21.9c-0.8-0.1-2.8-1-7.6-5.2l-0.3-0.3c0.1-0.7,0.3-1.4,0.5-2.1c2.1,0.4,4.3,0.8,4.7,0.9
c1.5,0.4,2.7,0.7,3.8,0.9c-1,0.1-1.8,0.4-2.3,1c-0.3,0.3-0.7,0.9-0.6,1.9c0.1,1.1,0.8,2.4,4,2.4c0.3,0,0.6,0,0.9,0
C11.8,21.7,10.7,21.9,10.1,21.9L10.1,21.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-2 0 24 24" style="overflow:visible;enable-background:new -2 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="12.0005" y1="0" x2="12.0005" y2="24.0005">
<stop offset="0" style="stop-color:#90C50E"/>
<stop offset="1" style="stop-color:#70A034"/>
<a:midPointStop offset="0" style="stop-color:#90C50E"/>
<a:midPointStop offset="0.5" style="stop-color:#90C50E"/>
<a:midPointStop offset="1" style="stop-color:#70A034"/>
</linearGradient>
<rect x="4" style="fill:url(#SVGID_1_);" width="16" height="24"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="12.0005" y1="1" x2="12.0005" y2="23.0005">
<stop offset="0" style="stop-color:#D9F991"/>
<stop offset="0.2388" style="stop-color:#D7F88D"/>
<stop offset="0.4501" style="stop-color:#D1F383"/>
<stop offset="0.6509" style="stop-color:#C6EC71"/>
<stop offset="0.844" style="stop-color:#B7E257"/>
<stop offset="1" style="stop-color:#A8D73D"/>
<a:midPointStop offset="0" style="stop-color:#D9F991"/>
<a:midPointStop offset="0.7317" style="stop-color:#D9F991"/>
<a:midPointStop offset="1" style="stop-color:#A8D73D"/>
</linearGradient>
<rect x="5" y="1" style="fill:url(#SVGID_2_);" width="14" height="22"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="12.0005" y1="2" x2="12.0005" y2="22.0005">
<stop offset="0" style="stop-color:#B3E810"/>
<stop offset="1" style="stop-color:#90C60D"/>
<a:midPointStop offset="0" style="stop-color:#B3E810"/>
<a:midPointStop offset="0.5" style="stop-color:#B3E810"/>
<a:midPointStop offset="1" style="stop-color:#90C60D"/>
</linearGradient>
<rect x="6" y="2" style="fill:url(#SVGID_3_);" width="12" height="20"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="12.0005" y1="4" x2="12.0005" y2="9">
<stop offset="0" style="stop-color:#90C50E"/>
<stop offset="1" style="stop-color:#70A034"/>
<a:midPointStop offset="0" style="stop-color:#90C50E"/>
<a:midPointStop offset="0.5" style="stop-color:#90C50E"/>
<a:midPointStop offset="1" style="stop-color:#70A034"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M7,4v5h10V4H7z M16,8H8V5h8V8z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="2.5" y1="0" x2="2.5" y2="24.0005">
<stop offset="0" style="stop-color:#656565"/>
<stop offset="1.342887e-02" style="stop-color:#646464"/>
<stop offset="0.4453" style="stop-color:#3C3C3C"/>
<stop offset="0.7891" style="stop-color:#242424"/>
<stop offset="1" style="stop-color:#1B1B1B"/>
<a:midPointStop offset="0" style="stop-color:#656565"/>
<a:midPointStop offset="0.4" style="stop-color:#656565"/>
<a:midPointStop offset="1" style="stop-color:#1B1B1B"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M4,0H2.6H1C0.5,0,0,0.5,0,1v22c0,0.5,0.5,1,1,1h1.6H4h1v-1V1V0H4z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="2.5" y1="1" x2="2.5" y2="23.0005">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="1" y="1" style="fill:url(#SVGID_6_);" width="3" height="22"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="2.5" y1="2" x2="2.5" y2="22.0005">
<stop offset="0" style="stop-color:#7C7C7C"/>
<stop offset="0.3898" style="stop-color:#5C5C5C"/>
<stop offset="0.768" style="stop-color:#444444"/>
<stop offset="1" style="stop-color:#3B3B3B"/>
<a:midPointStop offset="0" style="stop-color:#7C7C7C"/>
<a:midPointStop offset="0.4" style="stop-color:#7C7C7C"/>
<a:midPointStop offset="1" style="stop-color:#3B3B3B"/>
</linearGradient>
<rect x="2" y="2" style="fill:url(#SVGID_7_);" width="1" height="20"/>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-0.1 -0.1 24 24"
style="overflow:visible;enable-background:new -0.1 -0.1 24 24;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="10.9429" y1="0" x2="10.9429" y2="19.7881">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M10.8,0C4.7,0.1-0.1,4.3,0,9.3c0,2.6,1.5,5,3.7,6.6c0,0.1,0,0.2,0.1,0.3
c0.3,2-0.9,3.6-0.9,3.6s2.2-0.5,3.5-1.5c0.2-0.2,0.5-0.4,0.7-0.7c1.3,0.4,2.6,0.6,4.1,0.6c6-0.1,10.9-4.3,10.8-9.3
C21.8,3.9,16.8-0.1,10.8,0z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="10.9434" y1="1" x2="10.9434" y2="18.1289">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M4.6,18.1c0.1-0.6,0.2-1.3,0.1-2.1c0-0.1,0-0.2-0.1-0.3l-0.1-0.4l-0.3-0.3
C2.2,13.6,1,11.5,1,9.3C0.9,4.8,5.3,1.1,10.8,1L11,1c5.4,0,9.8,3.5,9.9,7.9c0.1,4.5-4.3,8.2-9.8,8.3l-0.2,0c-1.2,0-2.4-0.2-3.5-0.5
l-0.6-0.2l-0.4,0.5c-0.2,0.2-0.4,0.4-0.5,0.6C5.4,17.7,5,17.9,4.6,18.1z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="10.9434" y1="2" x2="10.9434" y2="16.1631">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M10.8,16.2c-1.1,0-2.2-0.2-3.2-0.5l-1.3-0.4L5.7,16c0,0,0-0.1,0-0.1c0-0.1,0-0.3-0.1-0.4
l-0.1-0.7l-0.6-0.6l0,0C3,13,2,11.2,2,9.3C1.9,5.3,5.9,2.1,10.8,2L11,2c4.8,0,8.8,3.1,8.8,6.9c0.1,3.9-3.9,7.2-8.8,7.2L10.8,16.2z"
/>
<path style="fill:#FFFFFF;" d="M16.6,9.6c0,0.7-0.6,1.3-1.2,1.3c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.2,1.3-1.2
C16,8.4,16.6,8.9,16.6,9.6z M11.5,8.4c-0.7,0-1.2,0.6-1.2,1.2c0,0.7,0.6,1.3,1.2,1.3c0.7,0,1.3-0.6,1.3-1.3
C12.7,8.9,12.2,8.4,11.5,8.4z M7.5,8.4c-0.7,0-1.3,0.6-1.3,1.2c0,0.7,0.6,1.3,1.3,1.3s1.3-0.6,1.3-1.3C8.8,8.9,8.2,8.4,7.5,8.4z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="14.0254" y1="6.667" x2="14.0254" y2="23.8398">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M20.7,20.5c1.9-1.4,3.2-3.4,3.2-5.7c0.1-4.4-4.3-8-9.8-8.1C8.7,6.6,4.2,10,4.1,14.4
c-0.1,4.4,4.3,8,9.8,8.1c1.4,0,2.7-0.2,3.9-0.5c1,1.3,3.7,1.9,3.7,1.9S20.3,22.2,20.7,20.5z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="14.1436" y1="7.667" x2="14.1436" y2="22.1943">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M19.9,22.2c-0.5-0.2-1-0.5-1.7-1.4c-0.4,0.1-1.7,0.7-4.2,0.7c-5,0-8.9-3.3-8.8-7.1
c0.1-3.7,4-6.8,9-6.8c2.3,0,4.7,0.8,6.3,2.2c1.6,1.3,2.5,3.1,2.4,4.9c0,1.9-1,3.7-3.1,5.1C19.7,20.7,19.7,21.6,19.9,22.2z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="14.0234" y1="8.6689" x2="14.0234" y2="20.5176">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<path style="fill:url(#SVGID_6_);" d="M13.9,20.5c-6.1-0.2-7.9-4.2-7.8-6.1c0.2-3.2,3.3-5.8,8-5.8c2.1,0,4.3,0.8,5.7,2
c1.4,1.1,2.1,2.6,2.1,4.1c-0.1,2.9-2.9,4.5-2.9,4.5s-0.2,0.7-0.2,0.9l-0.4-0.5C18.4,19.6,16.5,20.6,13.9,20.5z"/>
<path style="fill:#FFFFFF;" d="M19.4,14.9c0,0.7-0.6,1.3-1.2,1.3c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.2,1.3-1.2
C18.8,13.7,19.4,14.2,19.4,14.9z M14.3,13.7c-0.7,0-1.2,0.6-1.2,1.2c0,0.7,0.6,1.3,1.2,1.3c0.7,0,1.3-0.6,1.3-1.3
C15.5,14.2,15,13.7,14.3,13.7z M10.3,13.7c-0.7,0-1.3,0.6-1.3,1.2c0,0.7,0.6,1.3,1.3,1.3s1.3-0.6,1.3-1.3
C11.6,14.2,11,13.7,10.3,13.7z"/>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-4.2 -0.3 24 24"
style="overflow:visible;enable-background:new -4.2 -0.3 24 24;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="7.8237" y1="0" x2="7.8237" y2="23.3262">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M2.4,8.4C1.1,8.4,0,7.5,0,6.1C0,3.3,2.8,0,7.7,0c3.3,0,7.9,2.2,7.9,6c0,2-1.2,3.5-3.6,4.4
c-3.3,1.2-1.4,3.7-4.5,3.7c-1.3,0-2.1-0.8-2.1-2.1c0-2.7,2.8-4.2,2.8-6.9c0-0.7-0.3-1.6-1.1-1.6c-0.9,0-1,0.9-1,1.5
C5.8,7.1,4.5,8.4,2.4,8.4z M7.3,23.3c-2,0-3.6-1.6-3.6-3.6c0-2,1.6-3.6,3.6-3.6c2,0,3.6,1.6,3.6,3.6C10.8,21.7,9.2,23.3,7.3,23.3z"
/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="7.8237" y1="1" x2="7.8237" y2="22.3262">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M7.3,22.3c-1.4,0-2.6-1.1-2.6-2.6c0-1.4,1.1-2.6,2.6-2.6s2.6,1.1,2.6,2.6
C9.8,21.2,8.7,22.3,7.3,22.3z M7.6,13.1c-0.8,0-1.1-0.4-1.1-1.1c0-1.1,0.6-1.9,1.2-2.9c0.7-1.1,1.5-2.3,1.5-4c0-1.3-0.7-2.6-2.1-2.6
c-1.8,0-2,1.7-2,2.4C4.9,6,4.3,7.4,2.4,7.4C1.6,7.4,1,6.9,1,6.1C1,4,3.1,1,7.7,1c2.9,0,6.9,1.9,6.9,5c0,1.6-1,2.7-2.9,3.4
c-2,0.8-2.5,2-2.9,2.8C8.5,13,8.5,13.1,7.6,13.1z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="7.8237" y1="2.0986" x2="7.8237" y2="21.3262">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M7.3,21.3c-0.9,0-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6c0.9,0,1.6,0.7,1.6,1.6S8.2,21.3,7.3,21.3z
M7.6,12.1c-0.1,0-0.1,0-0.1,0c0,0,0-0.1,0-0.1c0-0.8,0.5-1.5,1-2.3c0.8-1.2,1.7-2.6,1.7-4.6c0-1.3-0.5-2.3-1.3-3
c2.2,0.4,4.8,1.8,4.8,3.9c0,0.4,0,1.6-2.3,2.5C9,9.4,8.3,11,7.9,11.9c0,0.1-0.1,0.2-0.1,0.2C7.8,12.1,7.7,12.1,7.6,12.1z M2.4,6.4
C2,6.4,2,6.2,2,6.1c0-1.1,0.9-2.7,2.7-3.5C4.4,3.1,4.1,3.8,4,4.8C3.9,6.2,3.1,6.4,2.4,6.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-2 -1 24 24" style="overflow:visible;enable-background:new -2 -1 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<radialGradient id="SVGID_1_" cx="10" cy="19.5" r="7.4917" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</radialGradient>
<path style="fill:url(#SVGID_1_);" d="M20,21c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2v-3c0-1.1,0.9-2,2-2h16c1.1,0,2,0.9,2,2V21z"/>
<radialGradient id="SVGID_2_" cx="10" cy="19.5" r="6.6049" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</radialGradient>
<path style="fill:url(#SVGID_2_);" d="M2,22c-0.6,0-1-0.4-1-1v-3c0-0.6,0.4-1,1-1h16c0.6,0,1,0.4,1,1v3c0,0.6-0.4,1-1,1H2z"/>
<radialGradient id="SVGID_3_" cx="10" cy="19.5" r="5.7554" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<rect x="2" y="18" style="fill:url(#SVGID_3_);" width="16" height="3"/>
<radialGradient id="SVGID_4_" cx="10" cy="11.5" r="7.4917" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</radialGradient>
<path style="fill:url(#SVGID_4_);" d="M20,13c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2v-3c0-1.1,0.9-2,2-2h16c1.1,0,2,0.9,2,2V13z"/>
<radialGradient id="SVGID_5_" cx="10" cy="11.5" r="6.6049" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</radialGradient>
<path style="fill:url(#SVGID_5_);" d="M2,14c-0.6,0-1-0.4-1-1v-3c0-0.6,0.4-1,1-1h16c0.6,0,1,0.4,1,1v3c0,0.6-0.4,1-1,1H2z"/>
<radialGradient id="SVGID_6_" cx="10" cy="11.5" r="5.7554" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<rect x="2" y="10" style="fill:url(#SVGID_6_);" width="16" height="3"/>
<radialGradient id="SVGID_7_" cx="10" cy="3.5" r="7.4917" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</radialGradient>
<path style="fill:url(#SVGID_7_);" d="M20,5c0,1.1-0.9,2-2,2H2C0.9,7,0,6.1,0,5V2c0-1.1,0.9-2,2-2h16c1.1,0,2,0.9,2,2V5z"/>
<radialGradient id="SVGID_8_" cx="10" cy="3.5" r="6.6049" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</radialGradient>
<path style="fill:url(#SVGID_8_);" d="M2,6C1.4,6,1,5.6,1,5V2c0-0.6,0.4-1,1-1h16c0.6,0,1,0.4,1,1v3c0,0.6-0.4,1-1,1H2z"/>
<radialGradient id="SVGID_9_" cx="10" cy="3.5" r="5.7554" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<rect x="2" y="2" style="fill:url(#SVGID_9_);" width="16" height="3"/>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-2 -1 24 24" style="overflow:visible;enable-background:new -2 -1 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<radialGradient id="SVGID_1_" cx="10" cy="19.5" r="7.4917" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</radialGradient>
<path style="fill:url(#SVGID_1_);" d="M20,21c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2v-3c0-1.1,0.9-2,2-2h16c1.1,0,2,0.9,2,2V21z"/>
<radialGradient id="SVGID_2_" cx="10" cy="19.5" r="6.6049" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</radialGradient>
<path style="fill:url(#SVGID_2_);" d="M2,22c-0.6,0-1-0.4-1-1v-3c0-0.6,0.4-1,1-1h16c0.6,0,1,0.4,1,1v3c0,0.6-0.4,1-1,1H2z"/>
<radialGradient id="SVGID_3_" cx="10" cy="19.5" r="5.7554" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<rect x="2" y="18" style="fill:url(#SVGID_3_);" width="16" height="3"/>
<radialGradient id="SVGID_4_" cx="10" cy="11.5" r="7.4917" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</radialGradient>
<path style="fill:url(#SVGID_4_);" d="M20,13c0,1.1-0.9,2-2,2H2c-1.1,0-2-0.9-2-2v-3c0-1.1,0.9-2,2-2h16c1.1,0,2,0.9,2,2V13z"/>
<radialGradient id="SVGID_5_" cx="10" cy="11.5" r="6.6049" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</radialGradient>
<path style="fill:url(#SVGID_5_);" d="M2,14c-0.6,0-1-0.4-1-1v-3c0-0.6,0.4-1,1-1h16c0.6,0,1,0.4,1,1v3c0,0.6-0.4,1-1,1H2z"/>
<radialGradient id="SVGID_6_" cx="10" cy="11.5" r="5.7554" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<rect x="2" y="10" style="fill:url(#SVGID_6_);" width="16" height="3"/>
<radialGradient id="SVGID_7_" cx="10" cy="3.5" r="7.4917" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</radialGradient>
<path style="fill:url(#SVGID_7_);" d="M20,5c0,1.1-0.9,2-2,2H2C0.9,7,0,6.1,0,5V2c0-1.1,0.9-2,2-2h16c1.1,0,2,0.9,2,2V5z"/>
<radialGradient id="SVGID_8_" cx="10" cy="3.5" r="6.6049" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</radialGradient>
<path style="fill:url(#SVGID_8_);" d="M2,6C1.4,6,1,5.6,1,5V2c0-0.6,0.4-1,1-1h16c0.6,0,1,0.4,1,1v3c0,0.6-0.4,1-1,1H2z"/>
<radialGradient id="SVGID_9_" cx="10" cy="3.5" r="5.7554" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<rect x="2" y="2" style="fill:url(#SVGID_9_);" width="16" height="3"/>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="24.001">
<stop offset="0" style="stop-color:#90C50E"/>
<stop offset="1" style="stop-color:#70A034"/>
<a:midPointStop offset="0" style="stop-color:#90C50E"/>
<a:midPointStop offset="0.5" style="stop-color:#90C50E"/>
<a:midPointStop offset="1" style="stop-color:#70A034"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M21.1,12.3c1,0,1.7,0.9,1.7,0.9c0.3,0.4,0.7,0.8,0.9,0.8s0.3-0.5,0.3-1V8c0-0.5-0.5-1-1-1h-3
c-0.5,0-1-0.1-1-0.3c0-0.2,0.3-0.7,0.7-1.1c0,0,0.8-0.9,0.8-2.1C20.5,1.6,18.9,0,17,0s-3.5,1.6-3.5,3.5c0,1.2,0.8,2.1,0.8,2.1
C14.7,6,15,6.5,15,6.7C15,6.9,14.5,7,14,7H8C7.5,7,7,7.5,7,8v6c0,0.5-0.1,1-0.3,1S6,14.7,5.6,14.3c0,0-0.9-0.8-2.1-0.8
C1.6,13.5,0,15.1,0,17s1.6,3.5,3.5,3.5c1.2,0,2.1-0.8,2.1-0.8C6,19.3,6.5,19,6.7,19S7,19.5,7,20v3c0,0.5,0.5,1,1,1h4
c0.5,0,1-0.1,1-0.3s-0.3-0.6-0.7-1c0,0-0.6-0.6-0.6-1.6c0-1.4,1.3-2.5,2.7-2.5c1.4,0,2.4,1.1,2.4,2.5c0,1-0.9,1.7-0.9,1.7
c-0.4,0.3-0.8,0.7-0.8,0.9s0.5,0.3,1,0.3h7c0.5,0,1-0.5,1-1v-6c0-0.5-0.1-1-0.3-1s-0.6,0.3-1,0.7c0,0-0.6,0.6-1.6,0.6
c-1.4,0-2.5-1.3-2.5-2.7S19.7,12.3,21.1,12.3z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="23.001">
<stop offset="0" style="stop-color:#D9F991"/>
<stop offset="0.2388" style="stop-color:#D7F88D"/>
<stop offset="0.4501" style="stop-color:#D1F383"/>
<stop offset="0.6509" style="stop-color:#C6EC71"/>
<stop offset="0.844" style="stop-color:#B7E257"/>
<stop offset="1" style="stop-color:#A8D73D"/>
<a:midPointStop offset="0" style="stop-color:#D9F991"/>
<a:midPointStop offset="0.7317" style="stop-color:#D9F991"/>
<a:midPointStop offset="1" style="stop-color:#A8D73D"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M17,23c0.4-0.4,0.7-1.1,0.7-1.9c0-2-1.5-3.5-3.4-3.5c-2,0-3.7,1.6-3.7,3.5
c0,0.9,0.3,1.5,0.6,1.9H8v-3c0-1.5-0.7-2-1.3-2c-0.6,0-1.3,0.6-1.7,0.9c0,0-0.7,0.6-1.5,0.6C2.1,19.5,1,18.4,1,17s1.1-2.5,2.5-2.5
c0.8,0,1.4,0.6,1.5,0.6C5.3,15.4,6.1,16,6.7,16C7.3,16,8,15.5,8,14V8h6c1.5,0,2-0.7,2-1.3c0-0.6-0.5-1.3-0.9-1.7
c0,0-0.6-0.7-0.6-1.5C14.5,2.1,15.6,1,17,1s2.5,1.1,2.5,2.5c0,0.8-0.6,1.5-0.6,1.5C18.5,5.4,18,6.1,18,6.7C18,7.3,18.5,8,20,8h3v4
c-0.4-0.4-1.1-0.7-1.9-0.7c-2,0-3.5,1.5-3.5,3.4c0,2,1.6,3.7,3.5,3.7c0.9,0,1.5-0.3,1.9-0.6V23H17z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="2" x2="11.9995" y2="22.001">
<stop offset="0" style="stop-color:#B3E810"/>
<stop offset="1" style="stop-color:#90C60D"/>
<a:midPointStop offset="0" style="stop-color:#B3E810"/>
<a:midPointStop offset="0.5" style="stop-color:#B3E810"/>
<a:midPointStop offset="1" style="stop-color:#90C60D"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M18.6,22c0.1-0.3,0.1-0.6,0.1-0.9c0-2.5-1.9-4.5-4.4-4.5c-2.5,0-4.7,2.1-4.7,4.5
c0,0.3,0,0.6,0.1,0.9H9v-2c0-2.1-1.2-3-2.3-3C7.8,17,9,16.1,9,14V9h5c2.1,0,3-1.2,3-2.3c0-0.7-0.4-1.5-1.2-2.4
c-0.1-0.1-0.3-0.5-0.3-0.8C15.5,2.7,16.2,2,17,2s1.5,0.7,1.5,1.5c0,0.3-0.3,0.7-0.3,0.8C17.4,5.2,17,6,17,6.7C17,7.8,17.9,9,20,9h2
v1.4c-0.3-0.1-0.6-0.1-0.9-0.1c-2.5,0-4.5,1.9-4.5,4.4c0,2.5,2.1,4.7,4.5,4.7c0.3,0,0.6,0,0.9-0.1V22H18.6z M3.5,18.5
C2.7,18.5,2,17.8,2,17s0.7-1.5,1.5-1.5c0.3,0,0.7,0.3,0.8,0.3C5.2,16.6,6,17,6.7,17c-0.7,0-1.5,0.4-2.4,1.2
C4.2,18.3,3.8,18.5,3.5,18.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="7.7681" y1="10.2231" x2="7.7681" y2="23.9805">
<stop offset="0" style="stop-color:#DB6D17"/>
<stop offset="1" style="stop-color:#BF3B08"/>
<a:midPointStop offset="0" style="stop-color:#DB6D17"/>
<a:midPointStop offset="0.5" style="stop-color:#DB6D17"/>
<a:midPointStop offset="1" style="stop-color:#BF3B08"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M10.9,19.1c-1.1-0.8-1.7-1.1-2-2.4c-0.2-1.1-1.3-6.4-1.3-6.4l-4.9,1c0,0,0.9,4.6,1.8,9
c0.9,4.4,1,4.3,6.8,3.1C13.7,22.8,12.8,20.5,10.9,19.1z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="7.8569" y1="11.3994" x2="7.8569" y2="22.9805">
<stop offset="0" style="stop-color:#F6A55E"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.5" style="stop-color:#F6A55E"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M7,23c-0.8,0-0.9,0-1.5-3l-1.6-8l2.9-0.6L8,16.9c0.3,1.6,1,2.1,1.9,2.7l0.4,0.3
c1.1,0.8,1.5,1.7,1.4,2.1c0,0.2-0.5,0.3-0.6,0.3l-0.5,0.1C9,22.7,7.8,23,7,23L7,23z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="7.7373" y1="12.5757" x2="7.7373" y2="21.8926">
<stop offset="0" style="stop-color:#F17219"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F17219"/>
<a:midPointStop offset="0.5" style="stop-color:#F17219"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M7.7,21.9c-0.7,0-0.7,0-1.2-2.1l-1.4-7l1-0.2L7,17.1c0.4,1.9,1.4,2.7,2.3,3.3l0.4,0.3
C10.8,21.6,10.6,21.4,7.7,21.9z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="11.0005" y1="0" x2="11.0005" y2="19.0039">
<stop offset="0" style="stop-color:#C3C3C3"/>
<stop offset="1" style="stop-color:#ACACAC"/>
<a:midPointStop offset="0" style="stop-color:#C3C3C3"/>
<a:midPointStop offset="0.5" style="stop-color:#C3C3C3"/>
<a:midPointStop offset="1" style="stop-color:#ACACAC"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M12.5,5H4.6C2.1,5,0,7.2,0,9.5C0,11.8,2.1,14,4.6,14h7.6c0,0,5.7,0,9.8,5c0-4.9,0-9.5,0-9.5
s0-4.3,0-9.5C18.7,4.8,12.5,5,12.5,5z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="11.0005" y1="2.6079" x2="11.0005" y2="16.5342">
<stop offset="0" style="stop-color:#E9E9E9"/>
<stop offset="1" style="stop-color:#C4C4C4"/>
<a:midPointStop offset="0" style="stop-color:#E9E9E9"/>
<a:midPointStop offset="0.5" style="stop-color:#E9E9E9"/>
<a:midPointStop offset="1" style="stop-color:#C4C4C4"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M21,16.5C17,13,12.5,13,12.2,13H4.6C2.7,13,1,11.4,1,9.5S2.7,6,4.6,6h7.8
c0.3,0,4.9-0.2,8.5-3.4V16.5z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="11.0005" y1="4.5991" x2="11.0005" y2="14.5273">
<stop offset="0" style="stop-color:#F7F7F7"/>
<stop offset="0.1044" style="stop-color:#FCFCFC"/>
<stop offset="0.3293" style="stop-color:#FFFFFF"/>
<stop offset="0.5692" style="stop-color:#E8E8E8"/>
<stop offset="0.8153" style="stop-color:#D7D7D7"/>
<stop offset="1" style="stop-color:#D1D1D1"/>
<a:midPointStop offset="0" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.2222" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.3293" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0.3545" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="1" style="stop-color:#D1D1D1"/>
</linearGradient>
<path style="fill:url(#SVGID_6_);" d="M20,14.5C16.2,12,12.4,12,12.2,12H4.6C3.3,12,2,10.8,2,9.5S3.3,7,4.6,7h7.8
c0.2,0,4-0.2,7.5-2.4V14.5z"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="5.501" y1="5.0015" x2="5.501" y2="14.002">
<stop offset="0" style="stop-color:#DB6D17"/>
<stop offset="1" style="stop-color:#BF3B08"/>
<a:midPointStop offset="0" style="stop-color:#DB6D17"/>
<a:midPointStop offset="0.5" style="stop-color:#DB6D17"/>
<a:midPointStop offset="1" style="stop-color:#BF3B08"/>
</linearGradient>
<path style="fill:url(#SVGID_7_);" d="M11,5H4.6C2.1,5,0,7.2,0,9.5C0,11.8,2.1,14,4.6,14H11V5z"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="6.001" y1="6.0015" x2="6.001" y2="13.0015">
<stop offset="0" style="stop-color:#F6A55E"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.5" style="stop-color:#F6A55E"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<path style="fill:url(#SVGID_8_);" d="M11,6H4.6C2.7,6,1,7.6,1,9.5S2.7,13,4.6,13H11V6z"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="6.501" y1="7.0015" x2="6.501" y2="12.0015">
<stop offset="0.2195" style="stop-color:#F6A55E"/>
<stop offset="0.5076" style="stop-color:#F28C3F"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0.2195" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.5304" style="stop-color:#F6A55E"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<path style="fill:url(#SVGID_9_);" d="M11,7H4.6C3.3,7,2,8.2,2,9.5S3.3,12,4.6,12H11V7z"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="22.002" y1="1.464844e-03" x2="22.002" y2="19.002">
<stop offset="0" style="stop-color:#DB6D17"/>
<stop offset="1" style="stop-color:#BF3B08"/>
<a:midPointStop offset="0" style="stop-color:#DB6D17"/>
<a:midPointStop offset="0.5" style="stop-color:#DB6D17"/>
<a:midPointStop offset="1" style="stop-color:#BF3B08"/>
</linearGradient>
<path style="fill:url(#SVGID_10_);" d="M20,17c0,1.1,0.9,2,2,2l0,0c1.1,0,2-0.9,2-2V2c0-1.1-0.9-2-2-2l0,0c-1.1,0-2,0.9-2,2V17z"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="22.002" y1="1.0015" x2="22.002" y2="18.002">
<stop offset="0" style="stop-color:#F6A55E"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.5" style="stop-color:#F6A55E"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<path style="fill:url(#SVGID_11_);" d="M22,18c-0.6,0-1-0.4-1-1V2c0-0.6,0.4-1,1-1s1,0.4,1,1v15C23,17.6,22.6,18,22,18z"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="22.002" y1="1.0015" x2="22.002" y2="18.002">
<stop offset="0" style="stop-color:#F17219"/>
<stop offset="9.009037e-02" style="stop-color:#F38A39"/>
<stop offset="0.183" style="stop-color:#F59E54"/>
<stop offset="0.2378" style="stop-color:#F6A55E"/>
<stop offset="0.2464" style="stop-color:#F5A35C"/>
<stop offset="0.3809" style="stop-color:#EC8740"/>
<stop offset="0.5155" style="stop-color:#E5722C"/>
<stop offset="0.649" style="stop-color:#E06620"/>
<stop offset="0.7805" style="stop-color:#DF621C"/>
<stop offset="1" style="stop-color:#D64701"/>
<a:midPointStop offset="0" style="stop-color:#F17219"/>
<a:midPointStop offset="0.4103" style="stop-color:#F17219"/>
<a:midPointStop offset="0.2378" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.296" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.7805" style="stop-color:#DF621C"/>
<a:midPointStop offset="0.5" style="stop-color:#DF621C"/>
<a:midPointStop offset="1" style="stop-color:#D64701"/>
</linearGradient>
<path style="fill:url(#SVGID_12_);" d="M22,18c-0.6,0-1-0.4-1-1V2c0-0.6,0.4-1,1-1s1,0.4,1,1v15C23,17.6,22.6,18,22,18z"/>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-3 0 24 24" style="overflow:visible;enable-background:new -3 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="9.4995" y1="0" x2="9.4995" y2="24.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);" points="11.5,0 0,0 0,24 19,24 19,7.9 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="9.4995" y1="1" x2="9.4995" y2="23.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="1,23 1,1 11.1,1 18,8.3 18,23 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="9.4995" y1="2" x2="9.4995" y2="22.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="2,22 2,2 10.6,2 17,8.7 17,22 "/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="14.2451" y1="0" x2="14.2451" y2="9.3594">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M10,9c0,0,5.2-1.5,9,0.4c0-0.1,0-1.5,0-1.5L11.5,0c0,0-1.8,0-2,0C12.1,3.7,10,9,10,9z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="11.3223" y1="7.5449" x2="14.4504" y2="4.4168">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="0.5181" style="stop-color:#E5F3FC"/>
<stop offset="0.7045" style="stop-color:#DEF0FB"/>
<stop offset="0.8371" style="stop-color:#D3EBFA"/>
<stop offset="0.872" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BDD8F0"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.87" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.872" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BDD8F0"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M17.5,7.8c-0.9-0.2-2-0.3-3.1-0.3c-1.1,0-2.1,0.1-3,0.3c0.4-1.6,0.7-4.1-0.2-6.4L17.5,7.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-0.1 -2 24 24"
style="overflow:visible;enable-background:new -0.1 -2 24 24;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="11.9351" y1="0" x2="11.9351" y2="20.0005">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M21.9,19c0,0.5-0.5,1-1,1h-18c-0.5,0-1-0.5-1-1V1.1c0-0.5,0.5-1.1,1-1.1h4
c0.5,0,1.4,0.3,1.8,0.6l0.9,0.7C10.1,1.7,10.9,2,11.4,2l9.5,0c0.5,0,1,0.5,1,1V19z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="11.9351" y1="0.9888" x2="11.9351" y2="19.0005">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M2.9,19V1.1C2.9,1.1,3,1,3,1l3.9,0c0.3,0,0.9,0.2,1.2,0.4L9,2.2C9.7,2.6,10.7,3,11.4,3l9.5,0
v16H2.9z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="11.9351" y1="1.9917" x2="11.9351" y2="18.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M3.9,18V2l3,0C7,2,7.4,2.1,7.5,2.2L8.4,3c0.8,0.6,2.1,1,3,1l8.5,0v14H3.9z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="11.936" y1="5" x2="11.936" y2="20.0005">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M23,19c0,0.5-0.5,1-1.1,1h-20c-0.5,0-1-0.5-1.1-1L0,6c0-0.5,0.4-1,0.9-1h22c0.5,0,1,0.5,0.9,1
L23,19z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="11.9673" y1="5.9541" x2="11.9673" y2="19.0005">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M1.9,19c0,0-0.1-0.1-0.1-0.1L1,6l21.9,0L22,18.9c0,0,0,0.1-0.1,0.1H1.9z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="11.9663" y1="6.9565" x2="11.9663" y2="18.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_6_);" points="2.8,18 2.1,7 21.9,7 21.1,18 "/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="10.4995" y1="0" x2="10.4995" y2="19.4312">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M19,0H2C0.9,0,0,0.9,0,2v11.3C0,14.4,0.9,15,2,15h0v4.4L6.1,15H19c1.1,0,2-0.5,2-1.6V2
C21,0.9,20,0,19,0z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="10.4995" y1="0.9531" x2="10.4995" y2="16.8384">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M3,14H2c-0.4,0-1-0.1-1-0.6V2c0-0.6,0.5-1,1-1H19c0.5,0,1,0.5,1,1v11.3c0,0.6-0.8,0.6-1,0.6
H5.7L3,16.8V14z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="10.4985" y1="1.9775" x2="10.4985" y2="14.314">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M4,13c0,0-2,0-2,0V2l17,0l0,11c0,0-13.8,0-13.8,0L4,14.3V13z"/>
<path style="fill:#FFFFFF;" d="M17,11H4v-1h13V11z M17,8H4v1h13V8z M17,6H4v1h13V6z M17,4H4v1h13V4z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="15" y1="7.8955" x2="15" y2="23.897">
<stop offset="0" style="stop-color:#90C50E"/>
<stop offset="1" style="stop-color:#70A034"/>
<a:midPointStop offset="0" style="stop-color:#90C50E"/>
<a:midPointStop offset="0.5" style="stop-color:#90C50E"/>
<a:midPointStop offset="1" style="stop-color:#70A034"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M22,7.9H8c-1.1,0-2,0.7-2,1.8v9c0,1.1,0.9,2,2,2v3.2l3.1-3H22c1.1,0,2-1.1,2-2.2v-9
C24,8.6,23.1,7.9,22,7.9z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="15" y1="8.8955" x2="15" y2="21.3911">
<stop offset="0" style="stop-color:#D9F991"/>
<stop offset="0.2388" style="stop-color:#D7F88D"/>
<stop offset="0.4501" style="stop-color:#D1F383"/>
<stop offset="0.6509" style="stop-color:#C6EC71"/>
<stop offset="0.844" style="stop-color:#B7E257"/>
<stop offset="1" style="stop-color:#A8D73D"/>
<a:midPointStop offset="0" style="stop-color:#D9F991"/>
<a:midPointStop offset="0.7317" style="stop-color:#D9F991"/>
<a:midPointStop offset="1" style="stop-color:#A8D73D"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M9,19.9H8c-0.6,0-1-0.7-1-1.2v-9c0-0.6,0.4-0.8,1-0.8h14c0.6,0,1,0.2,1,0.8v9
c0,0.6-0.4,1.2-1,1.2H10.6L9,21.4V19.9z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="15" y1="9.8955" x2="15" y2="18.896">
<stop offset="0" style="stop-color:#B3E810"/>
<stop offset="1" style="stop-color:#90C60D"/>
<a:midPointStop offset="0" style="stop-color:#B3E810"/>
<a:midPointStop offset="0.5" style="stop-color:#B3E810"/>
<a:midPointStop offset="1" style="stop-color:#90C60D"/>
</linearGradient>
<polygon style="fill:url(#SVGID_6_);" points="10,18.9 8,18.9 8,9.9 22,9.9 22,18.9 10.2,18.9 10,18.9 "/>
<path style="fill:#FFFFFF;" d="M20,16.9H10v-1h10V16.9z M20,13.9H10v1h10V13.9z M20,11.9H10v1h10V11.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-2 0 24 24" style="overflow:visible;enable-background:new -2 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="17.5" y1="16" x2="17.5" y2="22">
<stop offset="0" style="stop-color:#DB6D17"/>
<stop offset="1" style="stop-color:#BF3B08"/>
<a:midPointStop offset="0" style="stop-color:#DB6D17"/>
<a:midPointStop offset="0.5" style="stop-color:#DB6D17"/>
<a:midPointStop offset="1" style="stop-color:#BF3B08"/>
</linearGradient>
<rect x="15" y="16" style="fill:url(#SVGID_1_);" width="5" height="6"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="17.5" y1="17" x2="17.5" y2="21">
<stop offset="0" style="stop-color:#F6A55E"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.5" style="stop-color:#F6A55E"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<rect x="16" y="17" style="fill:url(#SVGID_2_);" width="3" height="4"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="17.5" y1="18" x2="17.5" y2="20">
<stop offset="0" style="stop-color:#F17219"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F17219"/>
<a:midPointStop offset="0.5" style="stop-color:#F17219"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<rect x="17" y="18" style="fill:url(#SVGID_3_);" width="1" height="2"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="17.5" y1="9" x2="17.5" y2="15.0005">
<stop offset="0" style="stop-color:#90C50E"/>
<stop offset="1" style="stop-color:#70A034"/>
<a:midPointStop offset="0" style="stop-color:#90C50E"/>
<a:midPointStop offset="0.5" style="stop-color:#90C50E"/>
<a:midPointStop offset="1" style="stop-color:#70A034"/>
</linearGradient>
<rect x="15" y="9" style="fill:url(#SVGID_4_);" width="5" height="6"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="17.5" y1="10" x2="17.5" y2="14.0005">
<stop offset="0" style="stop-color:#D9F991"/>
<stop offset="0.2388" style="stop-color:#D7F88D"/>
<stop offset="0.4501" style="stop-color:#D1F383"/>
<stop offset="0.6509" style="stop-color:#C6EC71"/>
<stop offset="0.844" style="stop-color:#B7E257"/>
<stop offset="1" style="stop-color:#A8D73D"/>
<a:midPointStop offset="0" style="stop-color:#D9F991"/>
<a:midPointStop offset="0.7317" style="stop-color:#D9F991"/>
<a:midPointStop offset="1" style="stop-color:#A8D73D"/>
</linearGradient>
<rect x="16" y="10" style="fill:url(#SVGID_5_);" width="3" height="4"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="17.5" y1="11" x2="17.5" y2="13">
<stop offset="0" style="stop-color:#B3E810"/>
<stop offset="1" style="stop-color:#90C60D"/>
<a:midPointStop offset="0" style="stop-color:#B3E810"/>
<a:midPointStop offset="0.5" style="stop-color:#B3E810"/>
<a:midPointStop offset="1" style="stop-color:#90C60D"/>
</linearGradient>
<rect x="17" y="11" style="fill:url(#SVGID_6_);" width="1" height="2"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="8.4995" y1="0" x2="8.4995" y2="24.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<rect style="fill:url(#SVGID_7_);" width="17" height="24"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="8.4995" y1="1" x2="8.4995" y2="23.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<rect x="1" y="1" style="fill:url(#SVGID_8_);" width="15" height="22"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="8.4995" y1="2" x2="8.4995" y2="22.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<rect x="2" y="2" style="fill:url(#SVGID_9_);" width="13" height="20"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="17.5" y1="2" x2="17.5" y2="8">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<rect x="15" y="2" style="fill:url(#SVGID_10_);" width="5" height="6"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="17.5" y1="3" x2="17.5" y2="7">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<rect x="16" y="3" style="fill:url(#SVGID_11_);" width="3" height="4"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="17.5" y1="4" x2="17.5" y2="6">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<rect x="17" y="4" style="fill:url(#SVGID_12_);" width="1" height="2"/>
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="12.4248" y1="10.7285" x2="12.4248" y2="15.9702">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="5.472010e-02" style="stop-color:#739DE9"/>
<stop offset="0.2045" style="stop-color:#6F95DE"/>
<stop offset="0.4149" style="stop-color:#6C91D7"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.13" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_13_);" d="M12.7,15.2C12,15.7,11.5,16,11,16c-0.3,0-0.5-0.1-0.7-0.3C10.1,15.5,10,15.3,10,15
c0-0.4,0.2-0.7,0.5-1c0.3-0.3,1-0.7,2.2-1.2v-0.5c0-0.4,0-0.6-0.1-0.7c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.1-0.4-0.1
c-0.2,0-0.4,0.1-0.6,0.2c-0.1,0.1-0.1,0.1-0.1,0.2c0,0.1,0,0.2,0.2,0.3c0.1,0.2,0.2,0.3,0.2,0.4c0,0.2-0.1,0.3-0.2,0.4
c-0.1,0.1-0.3,0.2-0.5,0.2c-0.2,0-0.4-0.1-0.6-0.2s-0.2-0.3-0.2-0.5c0-0.3,0.1-0.5,0.3-0.7c0.2-0.2,0.5-0.4,0.9-0.5s0.7-0.2,1.1-0.2
c0.5,0,0.9,0.1,1.1,0.3c0.3,0.2,0.5,0.4,0.5,0.7c0.1,0.2,0.1,0.5,0.1,1v1.9c0,0.2,0,0.4,0,0.4c0,0.1,0,0.1,0.1,0.1c0,0,0.1,0,0.1,0
c0.1,0,0.2-0.1,0.3-0.2l0.2,0.1c-0.2,0.3-0.4,0.5-0.6,0.6c-0.2,0.1-0.4,0.2-0.7,0.2c-0.3,0-0.5-0.1-0.7-0.2
C12.8,15.6,12.7,15.4,12.7,15.2z M12.7,14.8v-1.7c-0.4,0.3-0.8,0.5-1,0.8c-0.1,0.2-0.2,0.4-0.2,0.6c0,0.2,0.1,0.3,0.2,0.4
c0.1,0.1,0.2,0.1,0.4,0.1C12.2,15.1,12.4,15,12.7,14.8z"/>
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="6.3535" y1="8.2671" x2="6.3535" y2="15.7007">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="5.472010e-02" style="stop-color:#739DE9"/>
<stop offset="0.2045" style="stop-color:#6F95DE"/>
<stop offset="0.4149" style="stop-color:#6C91D7"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.13" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_14_);" d="M7,13.6H4.4l-0.3,0.7c-0.1,0.2-0.2,0.4-0.2,0.6c0,0.2,0.1,0.4,0.2,0.5
c0.1,0.1,0.3,0.1,0.7,0.1v0.2H2.5v-0.2c0.3,0,0.5-0.1,0.6-0.3c0.2-0.2,0.4-0.5,0.6-1.1l2.6-5.8h0.1l2.6,6c0.2,0.6,0.5,0.9,0.6,1.1
c0.1,0.1,0.3,0.2,0.5,0.2v0.2H6.7v-0.2h0.1c0.3,0,0.5,0,0.6-0.1c0.1-0.1,0.1-0.1,0.1-0.2c0-0.1,0-0.1,0-0.2c0,0-0.1-0.2-0.2-0.4
L7,13.6z M6.8,13.2l-1.1-2.5l-1.1,2.5H6.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 -2 24 24" style="overflow:visible;enable-background:new 0 -2 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="18" y1="10" x2="18" y2="20.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="13" y="10" style="fill:url(#SVGID_1_);" width="10" height="10"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="18" y1="11" x2="18" y2="19.0005">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="14" y="11" style="fill:url(#SVGID_2_);" width="8" height="8"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="18" y1="12" x2="18" y2="18">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="15" y="12" style="fill:url(#SVGID_3_);" width="6" height="6"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="18" y1="10" x2="18" y2="14.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="12" y="10" style="fill:url(#SVGID_4_);" width="12" height="4"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="18" y1="11" x2="18" y2="13.0005">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="13" y="11" style="fill:url(#SVGID_5_);" width="10" height="2"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="18" y1="10" x2="18" y2="16.4233">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<polygon style="fill:url(#SVGID_6_);" points="17,10 17,11.7 17,15 17,16.4 18,15.5 19,16.4 19,15 19,11.7 19,10 "/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="6" y1="10" x2="6" y2="20.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="1" y="10" style="fill:url(#SVGID_7_);" width="10" height="10"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="6" y1="11" x2="6" y2="19.0005">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="2" y="11" style="fill:url(#SVGID_8_);" width="8" height="8"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="6" y1="12" x2="6" y2="18">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="3" y="12" style="fill:url(#SVGID_9_);" width="6" height="6"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="6" y1="10" x2="6" y2="14.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect y="10" style="fill:url(#SVGID_10_);" width="12" height="4"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="6" y1="11" x2="6" y2="13.0005">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="1" y="11" style="fill:url(#SVGID_11_);" width="10" height="2"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="6" y1="10" x2="6" y2="16.4233">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<polygon style="fill:url(#SVGID_12_);" points="5,10 5,11.7 5,15 5,16.4 6,15.5 7,16.4 7,15 7,11.7 7,10 "/>
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="10">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="7" style="fill:url(#SVGID_13_);" width="10" height="10"/>
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="9">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="8" y="1" style="fill:url(#SVGID_14_);" width="8" height="8"/>
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="2" x2="11.9995" y2="8">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="9" y="2" style="fill:url(#SVGID_15_);" width="6" height="6"/>
<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="4">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="6" style="fill:url(#SVGID_16_);" width="12" height="4"/>
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="3">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="7" y="1" style="fill:url(#SVGID_17_);" width="10" height="2"/>
<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="6.4229">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<polygon style="fill:url(#SVGID_18_);" points="11,0 11,1.7 11,5 11,6.4 12,5.5 13,6.4 13,5 13,1.7 13,0 "/>
</svg>

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 -2 24 24" style="overflow:visible;enable-background:new 0 -2 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="18" y1="10" x2="18" y2="20.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="13" y="10" style="fill:url(#SVGID_1_);" width="10" height="10"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="18" y1="11" x2="18" y2="19.0005">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="14" y="11" style="fill:url(#SVGID_2_);" width="8" height="8"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="18" y1="12" x2="18" y2="18">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="15" y="12" style="fill:url(#SVGID_3_);" width="6" height="6"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="18" y1="10" x2="18" y2="14.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="12" y="10" style="fill:url(#SVGID_4_);" width="12" height="4"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="18" y1="11" x2="18" y2="13.0005">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="13" y="11" style="fill:url(#SVGID_5_);" width="10" height="2"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="18" y1="10" x2="18" y2="16.4233">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<polygon style="fill:url(#SVGID_6_);" points="17,10 17,11.7 17,15 17,16.4 18,15.5 19,16.4 19,15 19,11.7 19,10 "/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="6" y1="10" x2="6" y2="20.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="1" y="10" style="fill:url(#SVGID_7_);" width="10" height="10"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="6" y1="11" x2="6" y2="19.0005">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="2" y="11" style="fill:url(#SVGID_8_);" width="8" height="8"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="6" y1="12" x2="6" y2="18">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="3" y="12" style="fill:url(#SVGID_9_);" width="6" height="6"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="6" y1="10" x2="6" y2="14.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect y="10" style="fill:url(#SVGID_10_);" width="12" height="4"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="6" y1="11" x2="6" y2="13.0005">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="1" y="11" style="fill:url(#SVGID_11_);" width="10" height="2"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="6" y1="10" x2="6" y2="16.4233">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<polygon style="fill:url(#SVGID_12_);" points="5,10 5,11.7 5,15 5,16.4 6,15.5 7,16.4 7,15 7,11.7 7,10 "/>
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="10">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="7" style="fill:url(#SVGID_13_);" width="10" height="10"/>
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="9">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="8" y="1" style="fill:url(#SVGID_14_);" width="8" height="8"/>
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="2" x2="11.9995" y2="8">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="9" y="2" style="fill:url(#SVGID_15_);" width="6" height="6"/>
<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="4">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="6" style="fill:url(#SVGID_16_);" width="12" height="4"/>
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="3">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="7" y="1" style="fill:url(#SVGID_17_);" width="10" height="2"/>
<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="6.4229">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<polygon style="fill:url(#SVGID_18_);" points="11,0 11,1.7 11,5 11,6.4 12,5.5 13,6.4 13,5 13,1.7 13,0 "/>
</svg>

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="11.9854" y1="0" x2="11.9854" y2="24.0161">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M14.4,0L0.6,13.9c-0.8,0.8-0.8,2.1,0,2.8l6.7,6.7c0.8,0.8,2,0.8,2.8,0L24,9.6V0H14.4z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="11.9854" y1="1" x2="11.9854" y2="23.0161">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M8.7,23c-0.3,0-0.5-0.1-0.7-0.3L1.3,16C1.1,15.8,1,15.6,1,15.3c0-0.3,0.1-0.5,0.3-0.7L14.9,1
H23v8.2L9.4,22.7C9.2,22.9,9,23,8.7,23C8.7,23,8.7,23,8.7,23z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="11.9844" y1="2" x2="11.9844" y2="22.0142">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="2,15.3 15.3,2 22,2 22,8.8 8.7,22 "/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="8.7197" y1="9.9688" x2="8.7197" y2="20.6313">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<polygon style="fill:url(#SVGID_4_);" points="3.4,15.3 8.7,10 14.1,15.3 8.7,20.6 "/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="11.1465" y1="22.0312" x2="11.1465" y2="23.8711" gradientTransform="matrix(0.7071 -0.7071 0.7071 0.7071 -14.0909 8.2514)">
<stop offset="0" style="stop-color:#57C3F6"/>
<stop offset="0.1648" style="stop-color:#83D3F8"/>
<stop offset="0.3554" style="stop-color:#AFE3FB"/>
<stop offset="0.5396" style="stop-color:#D2EFFD"/>
<stop offset="0.7128" style="stop-color:#EBF8FE"/>
<stop offset="0.8709" style="stop-color:#FAFDFF"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0" style="stop-color:#57C3F6"/>
<a:midPointStop offset="0.3354" style="stop-color:#57C3F6"/>
<a:midPointStop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<polygon style="fill:url(#SVGID_5_);" points="7.4,17.9 8.7,19.2 12.6,15.3 11.3,14 "/>
<path style="fill:#F2EFD5;" d="M12.6,15.3L12.3,15c-0.3,0.2-0.8,0.5-1.4,1.1c-1.1,0.9-1,0.5-2,0.9c-0.4,0.2-0.9,0.6-1.4,1l1.2,1.2
L12.6,15.3z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="8.3882" y1="23.1035" x2="13.9038" y2="23.1035" gradientTransform="matrix(0.7071 -0.7071 0.7071 0.7071 -14.0909 8.2514)">
<stop offset="0" style="stop-color:#F8E5B5"/>
<stop offset="1" style="stop-color:#F9E5B6"/>
<a:midPointStop offset="0" style="stop-color:#F8E5B5"/>
<a:midPointStop offset="0.4451" style="stop-color:#F8E5B5"/>
<a:midPointStop offset="1" style="stop-color:#F9E5B6"/>
</linearGradient>
<path style="fill:url(#SVGID_6_);" d="M12.6,15.3l-0.2-0.2c-0.4,0.2-0.6,0.6-1.3,1.2C10,17.2,10,16.6,9,17c-0.4,0.2-0.9,0.6-1.3,1.1
l1.1,1.1L12.6,15.3z"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="12.1709" y1="17.6572" x2="10.1204" y2="22.7323" gradientTransform="matrix(0.7071 -0.7071 0.7071 0.7071 -14.0909 8.2514)">
<stop offset="0" style="stop-color:#57C3F6"/>
<stop offset="4.801393e-03" style="stop-color:#59C4F6"/>
<stop offset="0.1237" style="stop-color:#85D3F8"/>
<stop offset="0.2474" style="stop-color:#AAE1FA"/>
<stop offset="0.376" style="stop-color:#C9ECFC"/>
<stop offset="0.51" style="stop-color:#E1F4FD"/>
<stop offset="0.6519" style="stop-color:#F2FAFE"/>
<stop offset="0.807" style="stop-color:#FCFEFF"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0" style="stop-color:#57C3F6"/>
<a:midPointStop offset="0.25" style="stop-color:#57C3F6"/>
<a:midPointStop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<polygon style="fill:url(#SVGID_7_);" points="4.8,15.3 7.4,17.9 11.3,14 8.7,11.4 "/>
<path style="fill:#FFFFFF;" d="M9,11.6C8.7,11.8,8.7,12,8.7,12s-0.4-0.1-0.6,0.4c-0.1,0.4,0.3,0.5,0.3,0.5s0,0-0.1,0.1
c0,0.1,0.1,0.1,0.1,0.1s-0.2,0.1-0.1,0.4c0.1,0.3,0.3,0.3,0.3,0.3s-0.1,0.5,0.4,0.6c0.4,0.1,0.5-0.3,0.5-0.3s0.3,0,0.6-0.2
c0.3-0.2,0.4-0.5,0.4-0.5s0.1,0,0.2,0L9,11.6z"/>
<path style="fill:#FFFFFF;" d="M7.9,14.5c0,0-0.1,0-0.2,0.1c0,0.1,0.1,0.2,0.1,0.2s0,0,0,0c0,0,0,0,0,0s-0.1,0,0,0.1
C7.8,15,7.9,15,7.9,15s0,0.1,0.1,0.2c0.1,0,0.1-0.1,0.1-0.1s0.1,0,0.2,0c0.1-0.1,0.1-0.1,0.1-0.1s0.1,0,0.1-0.1c0-0.1,0-0.2,0-0.2
s0.2,0,0.1-0.2c-0.1-0.1-0.2,0-0.2,0s-0.1-0.1-0.1-0.1c-0.1,0-0.1,0.1-0.1,0.1s0,0,0,0c0,0-0.1,0-0.1,0S8,14.3,7.9,14.3
C7.8,14.4,7.9,14.5,7.9,14.5z"/>
<path style="fill:#FFFFFF;" d="M19.6,8.4l-5.5,5.5l-0.7-0.7l5.5-5.5L19.6,8.4z M17.5,6.3L12,11.8l0.7,0.7L18.2,7L17.5,6.3z
M16.1,4.9l-5.5,5.5l0.7,0.7l5.5-5.5L16.1,4.9z"/>
<ellipse style="fill:#FFFFFF;" cx="19.7" cy="4.3" rx="1.3" ry="1.3"/>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="5.5" y1="10" x2="5.5" y2="14.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<rect x="5" y="10" style="fill:url(#SVGID_1_);" width="1" height="4"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="15" y1="5" x2="15" y2="9">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="18,5 11,5 11,6 18,6 18,9 19,9 19,6 19,5 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="5.5" y1="14" x2="5.5" y2="24">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M10,14H1c-0.6,0-1,0.4-1,1v1v7v1h1h9h1v-1v-7v-1C11,14.4,10.6,14,10,14z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="5.5" y1="17" x2="5.5" y2="23">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<rect x="1" y="17" style="fill:url(#SVGID_4_);" width="9" height="6"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="5.5" y1="18" x2="5.5" y2="22">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<rect x="2" y="18" style="fill:url(#SVGID_5_);" width="7" height="4"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="5.5" y1="15" x2="5.5" y2="16">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<rect x="1" y="15" style="fill:url(#SVGID_6_);" width="9" height="1"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="18.5" y1="9" x2="18.5" y2="19.0005">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_7_);" d="M23,9h-9c-0.6,0-1,0.4-1,1v1v7v1h1h9h1v-1v-7v-1C24,9.4,23.6,9,23,9z"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="18.5" y1="12" x2="18.5" y2="18.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<rect x="14" y="12" style="fill:url(#SVGID_8_);" width="9" height="6"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="18.5" y1="13" x2="18.5" y2="17.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<rect x="15" y="13" style="fill:url(#SVGID_9_);" width="7" height="4"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="18.5" y1="10" x2="18.5" y2="11">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<rect x="14" y="10" style="fill:url(#SVGID_10_);" width="9" height="1"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="5.5" y1="0" x2="5.5" y2="10">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_11_);" d="M10,0H1C0.4,0,0,0.4,0,1v1v7v1h1h9h1V9V2V1C11,0.4,10.6,0,10,0z"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="5.5" y1="3" x2="5.5" y2="9">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<rect x="1" y="3" style="fill:url(#SVGID_12_);" width="9" height="6"/>
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="5.5" y1="4" x2="5.5" y2="8">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<rect x="2" y="4" style="fill:url(#SVGID_13_);" width="7" height="4"/>
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="5.5" y1="1" x2="5.5" y2="2">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<rect x="1" y="1" style="fill:url(#SVGID_14_);" width="9" height="1"/>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="24.001">
<stop offset="0" style="stop-color:#90C50E"/>
<stop offset="1" style="stop-color:#70A034"/>
<a:midPointStop offset="0" style="stop-color:#90C50E"/>
<a:midPointStop offset="0.5" style="stop-color:#90C50E"/>
<a:midPointStop offset="1" style="stop-color:#70A034"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M21.1,12.3c1,0,1.7,0.9,1.7,0.9c0.3,0.4,0.7,0.8,0.9,0.8s0.3-0.5,0.3-1V8c0-0.5-0.5-1-1-1h-3
c-0.5,0-1-0.1-1-0.3c0-0.2,0.3-0.7,0.7-1.1c0,0,0.8-0.9,0.8-2.1C20.5,1.6,18.9,0,17,0s-3.5,1.6-3.5,3.5c0,1.2,0.8,2.1,0.8,2.1
C14.7,6,15,6.5,15,6.7C15,6.9,14.5,7,14,7H8C7.5,7,7,7.5,7,8v6c0,0.5-0.1,1-0.3,1S6,14.7,5.6,14.3c0,0-0.9-0.8-2.1-0.8
C1.6,13.5,0,15.1,0,17s1.6,3.5,3.5,3.5c1.2,0,2.1-0.8,2.1-0.8C6,19.3,6.5,19,6.7,19S7,19.5,7,20v3c0,0.5,0.5,1,1,1h4
c0.5,0,1-0.1,1-0.3s-0.3-0.6-0.7-1c0,0-0.6-0.6-0.6-1.6c0-1.4,1.3-2.5,2.7-2.5c1.4,0,2.4,1.1,2.4,2.5c0,1-0.9,1.7-0.9,1.7
c-0.4,0.3-0.8,0.7-0.8,0.9s0.5,0.3,1,0.3h7c0.5,0,1-0.5,1-1v-6c0-0.5-0.1-1-0.3-1s-0.6,0.3-1,0.7c0,0-0.6,0.6-1.6,0.6
c-1.4,0-2.5-1.3-2.5-2.7S19.7,12.3,21.1,12.3z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="23.001">
<stop offset="0" style="stop-color:#D9F991"/>
<stop offset="0.2388" style="stop-color:#D7F88D"/>
<stop offset="0.4501" style="stop-color:#D1F383"/>
<stop offset="0.6509" style="stop-color:#C6EC71"/>
<stop offset="0.844" style="stop-color:#B7E257"/>
<stop offset="1" style="stop-color:#A8D73D"/>
<a:midPointStop offset="0" style="stop-color:#D9F991"/>
<a:midPointStop offset="0.7317" style="stop-color:#D9F991"/>
<a:midPointStop offset="1" style="stop-color:#A8D73D"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M17,23c0.4-0.4,0.7-1.1,0.7-1.9c0-2-1.5-3.5-3.4-3.5c-2,0-3.7,1.6-3.7,3.5
c0,0.9,0.3,1.5,0.6,1.9H8v-3c0-1.5-0.7-2-1.3-2c-0.6,0-1.3,0.6-1.7,0.9c0,0-0.7,0.6-1.5,0.6C2.1,19.5,1,18.4,1,17s1.1-2.5,2.5-2.5
c0.8,0,1.4,0.6,1.5,0.6C5.3,15.4,6.1,16,6.7,16C7.3,16,8,15.5,8,14V8h6c1.5,0,2-0.7,2-1.3c0-0.6-0.5-1.3-0.9-1.7
c0,0-0.6-0.7-0.6-1.5C14.5,2.1,15.6,1,17,1s2.5,1.1,2.5,2.5c0,0.8-0.6,1.5-0.6,1.5C18.5,5.4,18,6.1,18,6.7C18,7.3,18.5,8,20,8h3v4
c-0.4-0.4-1.1-0.7-1.9-0.7c-2,0-3.5,1.5-3.5,3.4c0,2,1.6,3.7,3.5,3.7c0.9,0,1.5-0.3,1.9-0.6V23H17z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="2" x2="11.9995" y2="22.001">
<stop offset="0" style="stop-color:#B3E810"/>
<stop offset="1" style="stop-color:#90C60D"/>
<a:midPointStop offset="0" style="stop-color:#B3E810"/>
<a:midPointStop offset="0.5" style="stop-color:#B3E810"/>
<a:midPointStop offset="1" style="stop-color:#90C60D"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M18.6,22c0.1-0.3,0.1-0.6,0.1-0.9c0-2.5-1.9-4.5-4.4-4.5c-2.5,0-4.7,2.1-4.7,4.5
c0,0.3,0,0.6,0.1,0.9H9v-2c0-2.1-1.2-3-2.3-3C7.8,17,9,16.1,9,14V9h5c2.1,0,3-1.2,3-2.3c0-0.7-0.4-1.5-1.2-2.4
c-0.1-0.1-0.3-0.5-0.3-0.8C15.5,2.7,16.2,2,17,2s1.5,0.7,1.5,1.5c0,0.3-0.3,0.7-0.3,0.8C17.4,5.2,17,6,17,6.7C17,7.8,17.9,9,20,9h2
v1.4c-0.3-0.1-0.6-0.1-0.9-0.1c-2.5,0-4.5,1.9-4.5,4.4c0,2.5,2.1,4.7,4.5,4.7c0.3,0,0.6,0,0.9-0.1V22H18.6z M3.5,18.5
C2.7,18.5,2,17.8,2,17s0.7-1.5,1.5-1.5c0.3,0,0.7,0.3,0.8,0.3C5.2,16.6,6,17,6.7,17c-0.7,0-1.5,0.4-2.4,1.2
C4.2,18.3,3.8,18.5,3.5,18.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-2 0 24 24" style="overflow:visible;enable-background:new -2 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="9.9995" y1="0" x2="9.9995" y2="24.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);" points="12.5,0 11.5,0 1,0 0,0 0,24 1,24 19,24 20,24 20,7.9 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="9.9995" y1="1" x2="9.9995" y2="23.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="12.1,1 11.1,1 2,1 1,1 1,23 2,23 18,23 19,23 19,8.3 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="9.9995" y1="2" x2="9.9995" y2="22.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="11.6,2 10.6,2 3,2 2,2 2,22 3,22 17,22 18,22 18,8.7 "/>
<path style="fill:#FFFFFF;" d="M16,21H4v-1h12V21z M16,18H4v1h12V18z M16,16H4v1h12V16z M16,14H4v1h12V14z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="9.9995" y1="4" x2="9.9995" y2="12">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<polygon style="fill:url(#SVGID_4_);" points="15.3,4 14.3,4 4,4 3,4 3,12 4,12 16,12 17,12 17,5.8 "/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="9.9995" y1="9" x2="9.9995" y2="11">
<stop offset="0" style="stop-color:#57C3F6"/>
<stop offset="0.1648" style="stop-color:#83D3F8"/>
<stop offset="0.3554" style="stop-color:#AFE3FB"/>
<stop offset="0.5396" style="stop-color:#D2EFFD"/>
<stop offset="0.7128" style="stop-color:#EBF8FE"/>
<stop offset="0.8709" style="stop-color:#FAFDFF"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0" style="stop-color:#57C3F6"/>
<a:midPointStop offset="0.3354" style="stop-color:#57C3F6"/>
<a:midPointStop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<rect x="4" y="9" style="fill:url(#SVGID_5_);" width="12" height="2"/>
<path style="fill:#F2EFD5;" d="M12.4,10.9c-0.5-0.2-1.1-0.3-2.7-0.4c-1.5-0.1-0.9-0.4-2-0.8C6.7,9.2,4,9.4,4,9.4V11h8.6
C12.6,11,12.5,10.9,12.4,10.9z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="4" y1="10.2476" x2="12.2959" y2="10.2476">
<stop offset="0" style="stop-color:#F8E5B5"/>
<stop offset="1" style="stop-color:#F9E5B6"/>
<a:midPointStop offset="0" style="stop-color:#F8E5B5"/>
<a:midPointStop offset="0.4451" style="stop-color:#F8E5B5"/>
<a:midPointStop offset="1" style="stop-color:#F9E5B6"/>
</linearGradient>
<path style="fill:url(#SVGID_6_);" d="M9.7,10.7c-1.5-0.1-0.9-0.6-2-1c-1-0.4-3.7,0-3.7,0V11h8.3C11.5,11,11.2,10.8,9.7,10.7z"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="12.5342" y1="1.5674" x2="8.163" y2="10.9413">
<stop offset="0" style="stop-color:#57C3F6"/>
<stop offset="0.2292" style="stop-color:#8AD5F9"/>
<stop offset="0.4827" style="stop-color:#BCE7FB"/>
<stop offset="0.705" style="stop-color:#E1F4FD"/>
<stop offset="0.885" style="stop-color:#F7FCFF"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0" style="stop-color:#57C3F6"/>
<a:midPointStop offset="0.3902" style="stop-color:#57C3F6"/>
<a:midPointStop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<rect x="4" y="5" style="fill:url(#SVGID_7_);" width="12" height="4"/>
<path style="fill:#FFFFFF;" d="M11.2,5.6c0,0-0.2-0.4-0.7-0.2c-0.4,0.3-0.1,0.7-0.1,0.7s-0.1,0-0.1,0c-0.1,0,0,0.2,0,0.2
s-0.3,0-0.4,0.2C9.6,6.9,9.8,7,9.8,7S9.3,7.4,9.6,7.8c0.3,0.4,0.6,0.1,0.6,0.1s0.2,0.3,0.6,0.3c0.4,0.1,0.6-0.1,0.6-0.1
s0.3,0.2,0.5,0.1C12.4,8.2,12.5,8,12.5,8s0.6,0.3,0.8-0.3C13.4,7.3,13,7.1,13,7.1s0.1-0.4-0.2-0.6s-0.6,0-0.6,0s0.1,0,0-0.1
c0-0.1-0.3-0.1-0.3-0.1s0.1-0.6-0.2-0.8C11.4,5.3,11.2,5.6,11.2,5.6z"/>
<path style="fill:#FFFFFF;" d="M8.6,6.9c0,0-0.1-0.1-0.2,0C8.3,6.9,8.4,7,8.4,7s0,0,0,0c0,0,0,0,0,0s-0.1,0-0.1,0.1
c0,0.1,0,0.1,0,0.1s-0.1,0.1,0,0.2c0.1,0.1,0.2,0,0.2,0s0.1,0.1,0.2,0.1c0.1,0,0.2,0,0.2,0s0.1,0.1,0.2,0C9,7.6,9,7.6,9,7.6
s0.2,0.1,0.2-0.1c0-0.1-0.1-0.2-0.1-0.2s0-0.1-0.1-0.2c-0.1,0-0.2,0-0.2,0s0,0,0,0s-0.1,0-0.1,0s0-0.2-0.1-0.2
C8.7,6.8,8.6,6.9,8.6,6.9z"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="15.2451" y1="0" x2="15.2451" y2="9.3594">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_8_);" d="M11,9c0,0,5.2-1.5,9,0.4c0-0.1,0-1.5,0-1.5L12.5,0c0,0-1.8,0-2,0C13.1,3.7,11,9,11,9z"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="12.3223" y1="7.5449" x2="15.4504" y2="4.4168">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="0.5181" style="stop-color:#E5F3FC"/>
<stop offset="0.7045" style="stop-color:#DEF0FB"/>
<stop offset="0.8371" style="stop-color:#D3EBFA"/>
<stop offset="0.872" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BDD8F0"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.87" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.872" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BDD8F0"/>
</linearGradient>
<path style="fill:url(#SVGID_9_);" d="M18.5,7.8c-0.9-0.2-2-0.3-3.1-0.3c-1.1,0-2.1,0.1-3,0.3c0.4-1.6,0.7-4.1-0.2-6.4L18.5,7.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="11.9565" y1="0" x2="11.9565" y2="24.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);" points="14.4,0 13.4,0 3,0 2,0 2,24 3,24 21,24 22,24 22,7.9 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="11.9565" y1="1" x2="11.9565" y2="23.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="14,1 13,1 4,1 3,1 3,23 4,23 20,23 21,23 21,8.3 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="11.9565" y1="2" x2="11.9565" y2="22.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="13.6,2 12.6,2 5,2 4,2 4,22 5,22 19,22 20,22 20,8.7 "/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="17.2021" y1="0" x2="17.2021" y2="9.3594">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M13,9c0,0,5.2-1.5,9,0.4c0-0.1,0-1.5,0-1.5L14.4,0c0,0-1.8,0-2,0C15.1,3.7,13,9,13,9z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="14.2793" y1="7.5449" x2="17.4074" y2="4.4168">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="0.5181" style="stop-color:#E5F3FC"/>
<stop offset="0.7045" style="stop-color:#DEF0FB"/>
<stop offset="0.8371" style="stop-color:#D3EBFA"/>
<stop offset="0.872" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BDD8F0"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.87" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.872" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BDD8F0"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M20.4,7.8c-0.9-0.2-2-0.3-3.1-0.3c-1.1,0-2.1,0.1-3,0.3c0.4-1.6,0.7-4.1-0.2-6.4L20.4,7.8z"/>
<g>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="11.8569" y1="1.8521" x2="11.8569" y2="23.9487">
<stop offset="0" style="stop-color:#DB6D17"/>
<stop offset="1" style="stop-color:#BF3B08"/>
<a:midPointStop offset="0" style="stop-color:#DB6D17"/>
<a:midPointStop offset="0.5" style="stop-color:#DB6D17"/>
<a:midPointStop offset="1" style="stop-color:#BF3B08"/>
</linearGradient>
<polygon style="fill:url(#SVGID_6_);" points="8,16.9 3.2,11.9 0,15.1 8.8,23.9 23.7,1.9 "/>
</g>
<g>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="9.5522" y1="9.0078" x2="9.5522" y2="22.3833">
<stop offset="0" style="stop-color:#F6A55E"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F6A55E"/>
<a:midPointStop offset="0.5" style="stop-color:#F6A55E"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<polygon style="fill:url(#SVGID_7_);" points="1.4,15.1 3.2,13.4 7.9,18.4 17.7,9 8.7,22.4 "/>
</g>
<g>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="7.2485" y1="14.7998" x2="7.2485" y2="20.8174">
<stop offset="0" style="stop-color:#F17219"/>
<stop offset="1" style="stop-color:#EA5B03"/>
<a:midPointStop offset="0" style="stop-color:#F17219"/>
<a:midPointStop offset="0.5" style="stop-color:#F17219"/>
<a:midPointStop offset="1" style="stop-color:#EA5B03"/>
</linearGradient>
<polygon style="fill:url(#SVGID_8_);" points="2.8,15.1 3.1,14.8 7.9,19.8 11.7,16.2 8.5,20.8 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="-3 0 24 24" style="overflow:visible;enable-background:new -3 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="9.4995" y1="0" x2="9.4995" y2="24.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);" points="11.5,0 0,0 0,24 19,24 19,7.9 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="9.4995" y1="1" x2="9.4995" y2="23.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="1,23 1,1 11.1,1 18,8.3 18,23 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="9.4995" y1="2" x2="9.4995" y2="22.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="2,22 2,2 10.6,2 17,8.7 17,22 "/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="14.2451" y1="0" x2="14.2451" y2="9.3594">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M10,9c0,0,5.2-1.5,9,0.4c0-0.1,0-1.5,0-1.5L11.5,0c0,0-1.8,0-2,0C12.1,3.7,10,9,10,9z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="11.3223" y1="7.5449" x2="14.4504" y2="4.4168">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="0.5181" style="stop-color:#E5F3FC"/>
<stop offset="0.7045" style="stop-color:#DEF0FB"/>
<stop offset="0.8371" style="stop-color:#D3EBFA"/>
<stop offset="0.872" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BDD8F0"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.87" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.872" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BDD8F0"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M17.5,7.8c-0.9-0.2-2-0.3-3.1-0.3c-1.1,0-2.1,0.1-3,0.3c0.4-1.6,0.7-4.1-0.2-6.4L17.5,7.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 -2 24 24" style="overflow:visible;enable-background:new 0 -2 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="20.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect x="1" style="fill:url(#SVGID_1_);" width="22" height="20"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="19.0005">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="2" y="1" style="fill:url(#SVGID_2_);" width="20" height="18"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="2" x2="11.9995" y2="18.0005">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="3" y="2" style="fill:url(#SVGID_3_);" width="18" height="16"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="7">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect style="fill:url(#SVGID_4_);" width="24" height="7"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="6">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="1" y="1" style="fill:url(#SVGID_5_);" width="22" height="5"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="2" x2="11.9995" y2="5">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="2" y="2" style="fill:url(#SVGID_6_);" width="20" height="3"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="11.4995" y1="0" x2="11.4995" y2="13.0005">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<polygon style="fill:url(#SVGID_7_);" points="9,0 9,3 9,10 9,13 11.5,11 14,13 14,10 14,3 14,0 "/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="11.4995" y1="1" x2="11.4995" y2="10.9355">
<stop offset="0" style="stop-color:#D58738"/>
<stop offset="1" style="stop-color:#AB551F"/>
<a:midPointStop offset="0" style="stop-color:#D58738"/>
<a:midPointStop offset="0.5" style="stop-color:#D58738"/>
<a:midPointStop offset="1" style="stop-color:#AB551F"/>
</linearGradient>
<polygon style="fill:url(#SVGID_8_);" points="10,1 10,4 10,7.9 10,10.9 11.5,9.7 13,10.9 13,7.9 13,4 13,1 "/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="11.5" y1="2" x2="11.5" y2="8.8711">
<stop offset="0" style="stop-color:#D0813A"/>
<stop offset="1" style="stop-color:#AF551D"/>
<a:midPointStop offset="0" style="stop-color:#D0813A"/>
<a:midPointStop offset="0.5" style="stop-color:#D0813A"/>
<a:midPointStop offset="1" style="stop-color:#AF551D"/>
</linearGradient>
<polygon style="fill:url(#SVGID_9_);" points="11,2 11,5 11,5.8 11,8.8 11.5,8.4 12,8.9 12,5.9 12,5 12,2 "/>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="20" y1="8" x2="20" y2="24.0005">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<rect x="16" y="8" style="fill:url(#SVGID_1_);" width="8" height="16"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="20" y1="9" x2="20" y2="23.0005">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<rect x="17" y="9" style="fill:url(#SVGID_2_);" width="6" height="14"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="20" y1="10" x2="20" y2="22.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<rect x="18" y="10" style="fill:url(#SVGID_3_);" width="4" height="12"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="0" x2="11.9995" y2="24.0005">
<stop offset="0" style="stop-color:#90C50E"/>
<stop offset="1" style="stop-color:#70A034"/>
<a:midPointStop offset="0" style="stop-color:#90C50E"/>
<a:midPointStop offset="0.5" style="stop-color:#90C50E"/>
<a:midPointStop offset="1" style="stop-color:#70A034"/>
</linearGradient>
<rect x="8" style="fill:url(#SVGID_4_);" width="8" height="24"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="1" x2="11.9995" y2="23.0005">
<stop offset="0" style="stop-color:#D9F991"/>
<stop offset="0.2388" style="stop-color:#D7F88D"/>
<stop offset="0.4501" style="stop-color:#D1F383"/>
<stop offset="0.6509" style="stop-color:#C6EC71"/>
<stop offset="0.844" style="stop-color:#B7E257"/>
<stop offset="1" style="stop-color:#A8D73D"/>
<a:midPointStop offset="0" style="stop-color:#D9F991"/>
<a:midPointStop offset="0.7317" style="stop-color:#D9F991"/>
<a:midPointStop offset="1" style="stop-color:#A8D73D"/>
</linearGradient>
<rect x="9" y="1" style="fill:url(#SVGID_5_);" width="6" height="22"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="11.9995" y1="2" x2="11.9995" y2="22.0005">
<stop offset="0" style="stop-color:#B3E810"/>
<stop offset="1" style="stop-color:#90C60D"/>
<a:midPointStop offset="0" style="stop-color:#B3E810"/>
<a:midPointStop offset="0.5" style="stop-color:#B3E810"/>
<a:midPointStop offset="1" style="stop-color:#90C60D"/>
</linearGradient>
<rect x="10" y="2" style="fill:url(#SVGID_6_);" width="4" height="20"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="4" y1="12" x2="4" y2="24.0005">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<rect y="12" style="fill:url(#SVGID_7_);" width="8" height="12"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="4" y1="13" x2="4" y2="23.0005">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<rect x="1" y="13" style="fill:url(#SVGID_8_);" width="6" height="10"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="4" y1="14" x2="4" y2="22">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<rect x="2" y="14" style="fill:url(#SVGID_9_);" width="4" height="8"/>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,485 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="11.9653" y1="0" x2="11.9653" y2="24.0005">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<polygon style="fill:url(#SVGID_1_);" points="14.4,0 13.4,0 3,0 2,0 2,24 3,24 21,24 22,24 22,7.9 "/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="11.9653" y1="1" x2="11.9653" y2="23.0005">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="1" style="stop-color:#DEEFFC"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.5" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="1" style="stop-color:#DEEFFC"/>
</linearGradient>
<polygon style="fill:url(#SVGID_2_);" points="14,1 13,1 4,1 3,1 3,23 4,23 20,23 21,23 21,8.3 "/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="11.9653" y1="2" x2="11.9653" y2="22.0005">
<stop offset="0" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BBDFF8"/>
<a:midPointStop offset="0" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BBDFF8"/>
</linearGradient>
<polygon style="fill:url(#SVGID_3_);" points="13.6,2 12.6,2 5,2 4,2 4,22 5,22 19,22 20,22 20,8.7 "/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="17.2109" y1="0" x2="17.2109" y2="9.3594">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M13,9c0,0,5.2-1.5,9,0.4c0-0.1,0-1.5,0-1.5L14.4,0c0,0-1.8,0-2,0C15.1,3.7,13,9,13,9z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="14.2881" y1="7.5449" x2="17.4162" y2="4.4168">
<stop offset="0" style="stop-color:#E7F4FC"/>
<stop offset="0.5181" style="stop-color:#E5F3FC"/>
<stop offset="0.7045" style="stop-color:#DEF0FB"/>
<stop offset="0.8371" style="stop-color:#D3EBFA"/>
<stop offset="0.872" style="stop-color:#CEE9F9"/>
<stop offset="1" style="stop-color:#BDD8F0"/>
<a:midPointStop offset="0" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.87" style="stop-color:#E7F4FC"/>
<a:midPointStop offset="0.872" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="0.5" style="stop-color:#CEE9F9"/>
<a:midPointStop offset="1" style="stop-color:#BDD8F0"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M20.5,7.8c-0.9-0.2-2-0.3-3.1-0.3c-1.1,0-2.1,0.1-3,0.3c0.4-1.6,0.7-4.1-0.2-6.4L20.5,7.8z"/>
<radialGradient id="SVGID_6_" cx="7.5312" cy="16.5" r="7.0005" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#8BB4F0"/>
<stop offset="7.721406e-02" style="stop-color:#88B1EF"/>
<stop offset="0.488" style="stop-color:#7FA7EC"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#8BB4F0"/>
<a:midPointStop offset="0.25" style="stop-color:#8BB4F0"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<path style="fill:url(#SVGID_6_);" d="M7.5,23.5C0.4,23.2-1.6,15.1,3,11.2c1.8-1.6,3.8-1.7,4.6-1.7c0.4,0,0.8,0,1.1,0.1
C9,9.6,9.4,9.7,9.7,9.8c0.3,0.1,0.7,0.3,1,0.4c0.3,0.2,0.6,0.4,0.9,0.6c0.3,0.2,0.6,0.4,0.8,0.7c0.3,0.3,0.5,0.5,0.7,0.8
c0.2,0.3,0.4,0.6,0.6,0.9c0.2,0.3,0.3,0.7,0.4,1c0.1,0.3,0.2,0.7,0.3,1.1c0.1,0.4,0.1,0.8,0.1,1.1s0,0.8-0.1,1.1
c-0.1,0.4-0.1,0.7-0.3,1.1c-0.1,0.3-0.3,0.7-0.4,1c-0.2,0.3-0.4,0.6-0.6,0.9c-0.2,0.3-0.4,0.6-0.7,0.8c-0.3,0.3-0.5,0.5-0.8,0.7
c-0.3,0.2-0.6,0.4-0.9,0.6c-0.3,0.2-0.7,0.3-1,0.4c-0.3,0.1-0.7,0.2-1.1,0.3C8.3,23.5,7.9,23.5,7.5,23.5"/>
<radialGradient id="SVGID_7_" cx="7.5308" cy="16.5" r="6.4856" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#8BB4F0"/>
<stop offset="7.721406e-02" style="stop-color:#88B1EF"/>
<stop offset="0.488" style="stop-color:#7FA7EC"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#8BB4F0"/>
<a:midPointStop offset="0.25" style="stop-color:#8BB4F0"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</radialGradient>
<path style="fill:url(#SVGID_7_);" d="M7.5,23C1,22.7-0.9,15.2,3.3,11.6C5,10.1,6.8,10,7.5,10c0.4,0,0.7,0,1.1,0.1
c0.3,0.1,0.7,0.1,1,0.2s0.6,0.2,0.9,0.4c0.3,0.2,0.6,0.3,0.9,0.5c0.3,0.2,0.5,0.4,0.8,0.6c0.2,0.2,0.5,0.5,0.6,0.8
c0.2,0.3,0.4,0.6,0.5,0.9s0.3,0.6,0.4,0.9s0.2,0.7,0.2,1c0.1,0.3,0.1,0.7,0.1,1.1c0,0.4,0,0.7-0.1,1.1c-0.1,0.3-0.1,0.7-0.2,1
s-0.2,0.6-0.4,0.9s-0.3,0.6-0.5,0.9s-0.4,0.5-0.6,0.8s-0.5,0.5-0.8,0.6c-0.3,0.2-0.6,0.4-0.9,0.5c-0.3,0.2-0.6,0.3-0.9,0.4
s-0.7,0.2-1,0.2C8.2,23,7.9,23,7.5,23"/>
<path style="fill:#B3E710;" d="M6.1,10.8L6.1,10.8c0-0.1,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0,0,0C6.1,10.7,6,10.7,6.1,10.8
c-0.1-0.1-0.1,0-0.2,0C5.9,10.7,6,10.8,6.1,10.8C6,10.8,6.1,10.8,6.1,10.8 M3,13c0,0,2,0,3.6,0c0,0,0.4-0.1,0.4-0.1l0,0v0l0,0v0v0
l0,0v0l0,0c0-0.1-0.3-0.1-0.4-0.1c0-0.1-0.2-0.2-0.1-0.4c0,0-0.1,0-0.1,0c-0.1-0.1-0.3-0.1-0.4-0.1c-0.1,0-0.2-0.1-0.3-0.2
c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0C5.6,12,5.6,12,5.4,11.9c0-0.2,0.2-0.3,0.4-0.5c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0.1,0,0.1,0
c0,0,0,0,0,0c0,0,0,0-0.1-0.1c0,0,0,0,0,0v0c0,0,0.1,0.1,0.2,0c0,0,0,0,0-0.1c0.1,0,0.1,0,0.2-0.1c0,0,0,0,0,0
c-0.1,0-0.1-0.1-0.2-0.1c0.1,0,0.1,0,0.2,0.1c0,0,0.1,0,0.2-0.1c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0
c0,0,0.1,0,0.1,0c0,0,0,0,0-0.1l0,0c0,0,0,0.1,0.1,0.1c0.1-0.1,0.1-0.1,0.2-0.1c0-0.1,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0-0.1c-0.1,0-0.1-0.1-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.2,0.2-0.2,0.2c-0.1,0,0-0.1,0-0.1c0.1,0,0.1,0,0-0.1
c-0.1,0-0.1,0.1-0.1,0.1c0,0,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0.1-0.1c0,0,0-0.1,0-0.1c0,0,0,0,0,0
c-0.1,0-0.2,0.1-0.2,0.1c0,0,0,0,0,0c-0.1,0-0.1,0-0.1,0.1c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0l-0.3,0.2c0,0,0,0,0,0c0,0,0,0,0.1-0.1c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0h0l0,0l0,0h0l0,0l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c-0.1,0-0.1,0-0.3,0h0l0,0c0,0,0,0,0,0h0l0,0c0,0,0,0,0,0h0l0,0c-0.2,0.1-0.2,0.1-0.3,0.2
c0-0.1,0-0.1,0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c-0.1,0-0.2,0-0.2,0c0.1,0,0.1,0,0.2-0.1c-0.1,0-0.1,0-0.1-0.1c-0.1,0-0.1,0-0.1,0
c0,0,0,0,0.1,0c0,0-0.1,0-0.1,0c0,0,0,0,0.1-0.1c0,0-0.3,0.1-0.5,0.2c0,0,0,0,0.1,0c0.1,0,0.2,0.1,0.3,0c0,0-0.1,0.2-0.1,0.2
c0,0,0,0,0,0c-0.1,0-0.1,0-0.1,0c-0.1,0-0.1,0-0.1,0c0,0,0.4,0,0.4,0v-0.1c0-0.1-0.1-0.2,0-0.2c0,0-0.1,0-0.1,0c0,0,0,0,0-0.1
c-0.1,0-0.2,0.1-0.3,0.1c-0.3,0.1-0.6,0.4-0.9,0.5c-0.1,0.1-0.3,0.2-0.4,0.3c0,0,0,0-0.1,0l0,0L3,11.8l0,0c0.1-0.1,0.1-0.1,0.2-0.2
c0,0,0,0,0,0c0,0-0.1,0.1-0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0.1-0.1,0.1-0.1,0.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0
c0,0,0,0.1,0,0.1c0,0,0,0,0,0c-0.1,0-0.1,0-0.1,0.1l0,0C3,12.2,3,12.2,2.9,12.3c0,0,0,0,0,0v0c0,0.1-0.1,0.1-0.1,0.1c0,0,0,0,0.1,0
l0,0c0,0.1-0.1,0.1-0.1,0.2c0,0,0,0.2,0,0.2c0,0,0,0.3-0.1,0.3c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0h0c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0.1c0,0,0,0,0,0
c0,0,0,0,0,0 M8.3,10.4C8.3,10.4,8.3,10.4,8.3,10.4L8.3,10.4C8.3,10.4,8.3,10.4,8.3,10.4C8.3,10.4,8.3,10.4,8.3,10.4 M8.3,10.4
c0,0-0.1-0.1-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0C8.2,10.4,8.2,10.4,8.3,10.4
C8.2,10.4,8.2,10.4,8.3,10.4L8.3,10.4L8.3,10.4L8.3,10.4C8.2,10.5,8.2,10.5,8.3,10.4C8.2,10.5,8.2,10.5,8.3,10.4
C8.2,10.5,8.3,10.5,8.3,10.4C8.3,10.4,8.3,10.4,8.3,10.4 M5.9,10.7L5.9,10.7C6,10.6,6,10.6,5.9,10.7c0-0.1,0-0.1,0-0.1
c0,0,0,0,0.1-0.1c0,0,0.1-0.1,0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c-0.1,0-0.1,0.1-0.2,0.1c0,0,0,0,0.1-0.1c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c-0.1,0.1-0.1,0.1-0.1,0.1c0.1,0,0.1,0,0.1,0c0,0-0.1,0-0.1,0c0,0,0.1,0,0.1-0.1c0,0-0.3,0.1-0.4,0.1
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0.1,0c0.1,0,0.1,0,0.1,0
c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0.1c0,0,0.1,0,0.2,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0.1,0
c0,0,0,0,0,0c0,0.1,0.1,0.1,0.1,0.1C5.8,10.7,5.8,10.7,5.9,10.7c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0C5.8,10.7,5.9,10.7,5.9,10.7
C5.9,10.7,5.9,10.7,5.9,10.7 M8.2,11L8.2,11C8.2,11,8.2,11,8.2,11c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1-0.1-0.1-0.1
c0,0-0.1,0-0.1,0c0-0.1-0.1,0-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0v0l0,0c0,0,0.1,0,0.1,0c0,0-0.1,0-0.1-0.1c0,0,0,0,0.1,0
c0,0,0,0-0.1,0c0,0,0,0-0.1,0c0,0,0,0,0,0l0,0c0,0,0,0,0.1,0c0,0-0.1,0-0.1,0c0,0,0,0-0.1,0c0,0,0,0,0,0v0c0,0,0,0-0.1,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0l0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c-0.1-0.1-0.1-0.1-0.1-0.1c0,0,0,0.1-0.1,0.1c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0-0.1-0.2,0c0,0,0,0,0,0c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0-0.1,0
c0,0,0,0,0,0c0,0,0,0,0,0c0-0.1,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0.1-0.1,0.1-0.1c0,0,0,0-0.1,0c-0.1,0-0.2,0.1-0.2,0.1c0,0,0,0,0,0
c0,0-0.1,0-0.1,0.1c0.1,0,0.1,0,0.1,0c0,0-0.1,0-0.1,0c0,0.1,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0.1,0,0.1,0,0.1,0c0,0-0.1,0-0.1,0l0,0c0,0,0,0,0.1,0c0,0,0.1,0,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0.1,0.1
c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0
s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0.1,0,0.1c0,0-0.1,0.1-0.1,0.1c0,0,0,0-0.1,0
c0,0,0.1,0,0.1,0.1c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0h0c-0.1-0.1-0.1,0-0.1,0c0,0,0,0,0,0c-0.1,0-0.1,0-0.1,0.1
c0.1,0,0.2,0,0.2,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0h0c0,0,0,0,0,0l0,0h0h0h0l0,0
c0,0,0,0,0.1,0.1c0,0,0,0,0,0c0,0.1,0.1,0,0.1,0.1c0,0,0.1,0,0.1,0.1c0.1,0,0.1,0,0.2,0c0,0,0,0,0,0c0-0.1-0.1-0.1-0.2-0.1
c-0.1,0-0.1,0-0.1-0.1c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0.1,0,0.1,0.1c0,0,0,0,0-0.1
c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1-0.1-0.1-0.1c0,0,0,0.1,0.1,0.1c0,0,0,0-0.1-0.1c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0-0.1,0-0.1-0.1
c0,0,0,0,0,0l0,0c0,0,0-0.1-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0-0.1c0.1,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0C7.9,11,7.9,11,8,11.1
c0,0,0,0.1,0.1,0c0,0.1,0,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0-0.1c0,0,0,0,0,0c0,0,0,0,0,0C8.2,11.1,8.2,11.1,8.2,11
C8.2,11,8.2,11,8.2,11C8.2,11,8.2,11,8.2,11C8.2,11,8.2,11,8.2,11 M6.4,10.4L6.4,10.4C6.5,10.4,6.4,10.4,6.4,10.4
C6.4,10.4,6.4,10.4,6.4,10.4c0-0.1,0.1-0.1,0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0
l0,0L6.4,10.4C6.4,10.4,6.4,10.4,6.4,10.4c-0.1-0.1-0.1,0-0.1,0c0,0,0,0,0,0c-0.1,0-0.1,0.1-0.1,0.1c0,0,0,0,0,0.1c0,0,0,0,0.1,0
c0,0,0,0,0,0c0,0,0,0,0,0C6.3,10.5,6.3,10.5,6.4,10.4C6.3,10.5,6.4,10.5,6.4,10.4 M8.1,10.3C8.1,10.3,8.1,10.3,8.1,10.3
C8.1,10.3,8.1,10.3,8.1,10.3C8.1,10.3,8.1,10.3,8.1,10.3C8.1,10.3,8.1,10.3,8.1,10.3 M6.8,10.3C6.8,10.3,6.8,10.3,6.8,10.3
C6.8,10.3,6.8,10.3,6.8,10.3C6.8,10.3,6.8,10.3,6.8,10.3C6.8,10.3,6.7,10.3,6.8,10.3C6.7,10.3,6.7,10.3,6.8,10.3c-0.1,0-0.1,0-0.2,0
c0,0,0,0-0.1,0c0,0,0,0.1-0.1,0.1c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0C6.6,10.4,6.8,10.3,6.8,10.3 M8.1,10.3
C8.1,10.3,8.1,10.3,8.1,10.3L8.1,10.3C8.1,10.3,8.1,10.3,8.1,10.3L8.1,10.3 M5.9,10.3L5.9,10.3C6,10.3,6,10.3,5.9,10.3
C6,10.3,6,10.3,5.9,10.3C6,10.3,6,10.3,5.9,10.3C6,10.3,6,10.3,5.9,10.3C6,10.3,6,10.3,5.9,10.3C6,10.3,5.9,10.3,5.9,10.3
c-0.1,0-0.1,0-0.2,0c-0.1,0-0.1,0-0.2,0.1l0,0l0,0l0,0h0l0,0l0,0l0,0l0,0c0,0-0.1,0-0.1,0.1c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0-0.1,0-0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0.1,0,0.1-0.1,0.2-0.1c0,0,0.1,0,0.1,0
C5.8,10.4,5.9,10.4,5.9,10.3 M7.9,10.2C7.9,10.2,7.9,10.2,7.9,10.2C7.9,10.2,7.9,10.2,7.9,10.2C7.9,10.2,7.9,10.2,7.9,10.2
C7.9,10.2,7.9,10.2,7.9,10.2 M7.2,10.2L7.2,10.2C7.2,10.2,7.2,10.2,7.2,10.2C7.2,10.2,7.2,10.2,7.2,10.2C7.2,10.2,7.2,10.2,7.2,10.2
c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0.1-0.1,0.1c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0.1,0,0.1,0,0.1,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0C7.1,10.3,7.1,10.3,7.2,10.2C7.2,10.2,7.2,10.2,7.2,10.2 M6.8,10.2C6.8,10.1,6.8,10.1,6.8,10.2
C6.8,10.1,6.8,10.1,6.8,10.2C6.8,10.1,6.8,10.1,6.8,10.2C6.8,10.2,6.8,10.2,6.8,10.2C6.8,10.1,6.8,10.1,6.8,10.2
C6.8,10.1,6.8,10.1,6.8,10.2C6.8,10.1,6.8,10.1,6.8,10.2C6.8,10.2,6.7,10.2,6.8,10.2L6.8,10.2C6.7,10.2,6.7,10.2,6.8,10.2
C6.7,10.1,6.7,10.2,6.8,10.2C6.7,10.2,6.7,10.2,6.8,10.2c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0s0,0,0,0s0,0,0,0c0,0,0,0,0,0s0,0,0,0
s0,0,0,0s0,0,0,0s0,0,0,0c0,0,0,0,0,0C6.6,10.2,6.7,10.2,6.8,10.2C6.7,10.2,6.7,10.2,6.8,10.2c-0.1,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0
c0,0,0,0,0.1,0C6.7,10.2,6.7,10.2,6.8,10.2 M6.5,10.2C6.6,10.2,6.6,10.2,6.5,10.2C6.6,10.2,6.6,10.2,6.5,10.2
C6.6,10.2,6.5,10.2,6.5,10.2C6.5,10.2,6.5,10.2,6.5,10.2c0,0,0.1,0,0.1-0.1c0,0,0,0,0,0C6.6,10.1,6.6,10.1,6.5,10.2
c-0.1,0-0.1,0-0.1,0C6.4,10.2,6.4,10.2,6.5,10.2c-0.1,0-0.1,0-0.1,0C6.5,10.2,6.5,10.2,6.5,10.2c-0.1,0-0.1,0-0.1,0c0,0,0,0-0.1,0
c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0.1,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0C6.5,10.2,6.5,10.2,6.5,10.2 M6.9,10.1C7,10.1,7,10.1,6.9,10.1C7,10.1,7,10.1,6.9,10.1C6.9,10.1,6.9,10.1,6.9,10.1
C6.9,10.1,6.9,10.1,6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1C6.9,10.1,6.9,10.1,6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1
C6.9,10.1,6.9,10.1,6.9,10.1C6.9,10.1,6.9,10.1,6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1L6.9,10.1
C6.9,10.1,6.9,10.1,6.9,10.1L6.9,10.1C6.9,10.1,6.9,10.1,6.9,10.1 M6.6,10.1C6.7,10.1,6.7,10.1,6.6,10.1C6.7,10.1,6.7,10.1,6.6,10.1
C6.7,10.1,6.6,10.1,6.6,10.1L6.6,10.1C6.6,10.1,6.6,10.1,6.6,10.1L6.6,10.1C6.6,10.1,6.6,10.1,6.6,10.1L6.6,10.1
C6.6,10.1,6.6,10.1,6.6,10.1L6.6,10.1C6.6,10.1,6.6,10.1,6.6,10.1c-0.1,0-0.3,0.1-0.3,0.1c0,0,0,0,0,0c0,0,0,0-0.1,0
c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0,0-0.1,0-0.1,0c0,0,0.1,0,0.1,0C6.6,10.1,6.6,10.1,6.6,10.1 M6.8,10.1L6.8,10.1
C6.8,10.1,6.8,10.1,6.8,10.1C6.8,10.1,6.8,10.1,6.8,10.1L6.8,10.1L6.8,10.1L6.8,10.1L6.8,10.1L6.8,10.1L6.8,10.1
C6.8,10.1,6.8,10.1,6.8,10.1L6.8,10.1C6.8,10.1,6.8,10.1,6.8,10.1c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0C6.8,10.1,6.8,10.1,6.8,10.1
M7.1,10.1C7.1,10.1,7.1,10.1,7.1,10.1C7.1,10,7.1,10,7.1,10.1C7.1,10,7.1,10,7.1,10.1L7.1,10.1L7.1,10.1L7.1,10.1L7.1,10.1
L7.1,10.1L7.1,10.1L7.1,10.1L7.1,10.1C7.1,10,7.1,10,7.1,10.1C7.1,10.1,7.1,10.1,7.1,10.1C7,10.1,7,10.1,7.1,10.1
C7.1,10.1,7.1,10.1,7.1,10.1 M7,10.1c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
C7.1,10,7,10.1,7,10.1C7,10.1,7,10.1,7,10.1C7,10,7,10.1,7,10.1C7,10.1,7,10.1,7,10.1C7,10.1,7,10.1,7,10.1C7,10.1,7,10.1,7,10.1
C7,10.1,7,10.1,7,10.1C7,10.1,7,10.1,7,10.1 M7.3,10C7.3,10,7.4,10,7.3,10C7.4,10,7.3,10,7.3,10C7.3,10,7.4,10,7.3,10
C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10
C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10c0.1,0,0.1,0,0.1,0
C7.4,10,7.4,10,7.3,10c0.1,0,0.1,0,0.2,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0C7.5,10,7.4,10,7.3,10C7.4,10,7.4,10,7.3,10
C7.3,10,7.3,10,7.3,10L7.3,10C7.3,10,7.3,10,7.3,10C7.3,10,7.3,10,7.3,10C7.3,10,7.3,10,7.3,10c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C7.2,10.1,7.2,10.1,7.3,10C7.3,10,7.3,10,7.3,10C7.3,10.1,7.3,10,7.3,10
C7.3,10,7.3,10,7.3,10C7.3,10,7.3,10,7.3,10 M7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10
C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10 M7.5,10L7.5,10L7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10
C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10L7.5,10C7.5,10,7.5,10,7.5,10L7.5,10
C7.5,10,7.5,10,7.5,10L7.5,10C7.5,10,7.5,10,7.5,10L7.5,10C7.5,10,7.5,10,7.5,10c-0.1,0-0.1,0-0.1,0C7.4,10,7.4,10,7.5,10
C7.4,10,7.4,10,7.5,10L7.5,10L7.5,10L7.5,10L7.5,10L7.5,10L7.5,10L7.5,10c-0.1,0-0.1,0-0.1,0l0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0h0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0
C7.4,10.1,7.4,10.1,7.5,10C7.4,10.1,7.4,10.1,7.5,10C7.4,10.1,7.4,10.1,7.5,10C7.4,10.1,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10
C7.5,10,7.5,10,7.5,10L7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10
C7.5,10,7.5,10,7.5,10C7.5,10,7.5,10,7.5,10 M9,11.2C8.6,10.5,8.1,10,7.5,10h0h0h0c0,0,0,0,0,0l0,0h0l0,0l0,0l0,0c0,0,0,0,0,0
c0,0,0,0,0,0l0,0l0,0l0,0l0,0l0,0c0,0,0,0,0,0v0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0h0c0,0,0,0,0.1,0c0,0,0,0,0.1,0
c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0l0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0
l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0h0c0,0,0,0,0,0h0c0,0,0,0,0,0h0h0c0,0,0,0,0,0h0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0h0h0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0h0l0,0l0,0h0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0h0c0,0,0,0,0.1,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0c0,0,0,0,0,0
c0,0,0,0,0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0h0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0v0
l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0-0.1,0-0.1,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0v0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c-0.1,0-0.1,0-0.1,0l0,0c0,0,0.1,0,0.1,0l0,0l0,0
c0,0,0,0,0,0c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0-0.1,0h0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
l0,0c0,0,0.1,0,0.1,0c0,0,0,0,0.1-0.1l0,0l0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0.1l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0
c0,0,0,0,0.1,0c0,0,0,0,0,0.1l0,0c0,0,0,0,0-0.1l0,0l0,0c0,0,0,0,0,0h0l0,0c0,0,0,0,0-0.1l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0.1,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1-0.1-0.1,0l0,0l0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0.1,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0l0,0c0,0,0,0,0,0C8.9,11.1,8.9,11.1,9,11.2C8.9,11.1,8.9,11.1,9,11.2L9,11.2C8.9,11.2,8.9,11.2,9,11.2
C8.9,11.2,8.9,11.2,9,11.2C8.9,11.2,8.9,11.2,9,11.2C8.9,11.2,8.9,11.2,9,11.2C8.9,11.2,8.9,11.2,9,11.2C8.9,11.2,8.9,11.2,9,11.2
C8.9,11.2,8.9,11.2,9,11.2C8.9,11.2,8.9,11.2,9,11.2C8.9,11.2,8.9,11.2,9,11.2C8.9,11.2,9,11.2,9,11.2C9,11.2,9,11.2,9,11.2"/>
<path style="fill:#B3E710;" d="M7.4,22.9L7.4,22.9C7.4,22.9,7.4,22.9,7.4,22.9L7.4,22.9C7.4,22.9,7.4,22.9,7.4,22.9L7.4,22.9
C7.4,22.9,7.4,22.9,7.4,22.9C7.4,22.9,7.4,22.9,7.4,22.9 M9.4,20.1C9.4,20.1,9.4,20.1,9.4,20.1c-0.1,0-0.1,0-0.2,0c0,0,0,0.1,0,0.1
C9.2,20.2,9.3,20.2,9.4,20.1 M8.8,22.1c0.3-0.5,0.6-1.2,0.8-2c0,0,0,0,0,0c0,0,0,0-0.1,0c-0.1,0-0.1,0.1-0.2,0.2c0,0,0,0,0,0
c0,0-0.1,0-0.1,0c0,0,0-0.1,0-0.1c-0.1,0-0.1,0-0.1,0c0,0,0-0.1,0.1-0.1c-0.5,0-1.1,0-1.7,0c-0.5,0-1,0-1.4,0c0,0,0,0.1,0,0.1
c0,0,0,0.1,0,0.2l0,0c0.1,0.1,0.1,0,0.1,0c0.1,0.1-0.1,0.1-0.1,0.2c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0.1,0.1,0.2,0.1,0.6,0.7
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0.1,0.2,0.4,0.2,0.5,0.3
c0.1,0.1-0.1,0.3-0.1,0.4c0,0-0.1,0-0.1,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0c0,0,0,0,0,0s0,0,0,0l0.1,0
c0,0.1,0.1,0.7,0.1,0.7c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0l0,0l0,0c0,0,0,0,0,0l0,0
c0,0,0,0,0,0h0c0,0,0,0,0,0h0h0c0,0,0,0,0,0c0,0,0,0,0,0l0,0h0l0,0l0,0l0,0h0c0,0,0-0.1,0-0.1c0,0,0,0,0.1-0.1c0,0,0.1,0,0.2-0.1
c0,0,0,0,0-0.1c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0.1,0,0.2,0,0.4-0.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0-0.1,0.1-0.1,0.1c0.2-0.1,0.2-0.1,0.4-0.3c0,0,0,0,0,0C8.7,22.1,8.8,22.1,8.8,22.1 M13.7,18.3C13.7,18.3,13.7,18.3,13.7,18.3
C13.7,18.3,13.7,18.3,13.7,18.3C13.7,18.3,13.7,18.3,13.7,18.3C13.7,18.3,13.7,18.4,13.7,18.3L13.7,18.3
C13.7,18.4,13.7,18.3,13.7,18.3 M14,15.4c0-0.2-0.1-0.5-0.1-0.7v0c0-0.1-0.1-0.1-0.2-0.2c0,0-0.1,0-0.3-0.6c0,0,0,0,0,0
c0-0.1,0-0.1-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0-0.1,0c0,0,0,0-0.1,0.1c0,0,0,0,0,0.1c0,0,0,0.1-0.1,0.1
c0,0,0,0-0.1,0c-0.1,0-0.1,0-0.1-0.1c0,0-0.1,0.5,0,0.7c0.1,0.3-0.2,0.4-0.2,0.7c0,0.2-0.1,0.4-0.1,0.7c0,0,0,0,0,0
c0.1,0.1,0.1,0.7,0,0.8c0,0,0,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0.1,0,0.1c0,0,0,0,0,0l0,0l0,0l0,0l0,0h0l0,0l0,0l0-0.1
c0,0,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0.2,0,0.2c0,0,0.1,0.1,0.1,0.1c0,0,0.1,0.1,0.1,0.1v0c0,0-0.1,0-0.1,0c0,0,0,0,0.1,0.2
c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0v0v0L12.8,18c0,0,0,0,0,0c0,0,0.2,0.3,0.3,0.3
c0.1,0,0.1-0.2,0.2-0.2c0,0,0,0,0-0.1c0,0,0,0,0,0c0.1,0,0.3-0.2,0.3-0.2c0,0,0.2,0,0.2,0.1l0.2,0v0c0,0.1-0.2,0.1-0.2,0.1
c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0.1,0.1,0.1,0.1v0l-0.1,0c0,0.1-0.1,0.2-0.2,0.3l0,0c0,0,0,0.1,0,0.1c0,0,0,0,0,0
c0,0,0,0.1-0.1,0.2l0,0l0,0c0,0,0,0,0,0.1c-0.1,0.4-0.5,1-0.5,1c0,0,0,0,0,0s0,0,0,0c0.1,0,0.2-0.3,0.3-0.6c0.2-0.3,0.3-0.6,0.4-0.9
s0.2-0.6,0.2-1c0.1-0.3,0.1-0.7,0.1-1C14.1,16.1,14.1,15.8,14,15.4 M13.4,13.8C13.4,13.8,13.4,13.8,13.4,13.8
C13.4,13.8,13.4,13.8,13.4,13.8C13.4,13.8,13.4,13.8,13.4,13.8C13.4,13.8,13.4,13.8,13.4,13.8C13.4,13.8,13.4,13.8,13.4,13.8
c0,0.1,0,0.1,0.1,0.2C13.5,13.9,13.5,13.9,13.4,13.8 M13.2,13.5C13.2,13.5,13.2,13.5,13.2,13.5C13.2,13.4,13.2,13.4,13.2,13.5
C13.2,13.5,13.2,13.5,13.2,13.5C13.2,13.5,13.2,13.5,13.2,13.5C13.2,13.5,13.2,13.5,13.2,13.5c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C13.3,13.6,13.3,13.6,13.2,13.5 M13.1,13.3C13.1,13.3,13.1,13.2,13.1,13.3
L13.1,13.3L13.1,13.3C13.1,13.3,13.1,13.3,13.1,13.3L13.1,13.3C13.1,13.3,13.1,13.3,13.1,13.3C13.1,13.3,13.1,13.3,13.1,13.3
C13.1,13.3,13.1,13.3,13.1,13.3C13.1,13.3,13.1,13.3,13.1,13.3L13.1,13.3L13.1,13.3L13.1,13.3L13.1,13.3L13.1,13.3L13.1,13.3
c0,0.1,0.1,0.1,0.1,0.1l0,0C13.2,13.4,13.1,13.3,13.1,13.3 M13.3,13.5C13.3,13.5,13.2,13.5,13.3,13.5l-0.1-0.1c0,0,0,0,0,0
c0,0,0,0,0,0c0,0-0.2-0.4-0.3-0.4l0,0c0,0-0.1,0-0.3,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0,0,0l0,0l0,0
c0,0,0.1,0.1,0.1,0.2c0,0,0,0-0.1,0c0,0.1-0.1,0-0.1,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0.1,0,0.1,0.1
c0.1,0.1,0.1,0.3,0.1,0.4c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0.1
c0,0,0,0.1,0,0.1c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0.1,0.1,0.1c0,0.1,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0l0,0h0
c0,0,0-0.1,0-0.1c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0,0,0,0
c0,0,0,0-0.1-0.1c0-0.1,0-0.1,0-0.2l0,0c0,0,0-0.1,0-0.1c0-0.1,0-0.1,0-0.1c-0.1-0.1-0.1-0.1-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0,0,0,0C13,13,13.3,13.5,13.3,13.5C13.3,13.5,13.3,13.5,13.3,13.5L13.3,13.5
L13.3,13.5L13.3,13.5L13.3,13.5C13.3,13.5,13.3,13.5,13.3,13.5C13.3,13.5,13.3,13.5,13.3,13.5C13.3,13.5,13.3,13.6,13.3,13.5
C13.3,13.6,13.3,13.6,13.3,13.5c0.1,0.1,0.1,0.2,0.1,0.2c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0.1c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0-0.1
C13.4,13.7,13.3,13.6,13.3,13.5 M12.9,12.9C12.9,12.9,12.9,12.9,12.9,12.9C12.9,12.9,12.9,12.9,12.9,12.9C12.9,12.9,13,13,12.9,12.9
C13,13,12.9,12.9,12.9,12.9 M13.1,13.1c0-0.1-0.1-0.1-0.1-0.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C13,13,13,13,13.1,13.1
C13,13,13,13,13.1,13.1C13,13.1,13.1,13.1,13.1,13.1C13.1,13.1,13.1,13.1,13.1,13.1 M9.2,12.9L9.2,12.9L9.2,12.9L9.2,12.9L9.2,12.9
c-0.1,0-0.1,0-0.1,0.1C9.1,12.9,9.1,12.9,9.2,12.9C9.2,12.9,9.2,12.9,9.2,12.9C9.2,12.9,9.2,12.9,9.2,12.9 M2.7,12.5
C2.8,12.5,2.7,12.5,2.7,12.5C2.7,12.5,2.7,12.5,2.7,12.5C2.7,12.6,2.7,12.6,2.7,12.5C2.7,12.6,2.7,12.6,2.7,12.5 M2.9,12.4
C2.9,12.4,2.9,12.4,2.9,12.4C2.9,12.3,2.9,12.3,2.9,12.4c0.1-0.1,0.1-0.1,0.1-0.1c0,0,0,0,0,0C2.8,12.3,2.8,12.4,2.9,12.4
C2.8,12.4,2.8,12.4,2.9,12.4C2.8,12.4,2.8,12.4,2.9,12.4C2.8,12.4,2.8,12.4,2.9,12.4C2.8,12.4,2.8,12.4,2.9,12.4
C2.8,12.4,2.8,12.4,2.9,12.4C2.8,12.4,2.8,12.4,2.9,12.4C2.9,12.4,2.9,12.4,2.9,12.4 M2.9,12.2C3,12.1,3,12.1,2.9,12.2
C3,12.1,3,12.1,2.9,12.2C3,12.1,3,12.1,2.9,12.2C2.9,12.1,2.9,12.2,2.9,12.2C2.9,12.2,2.9,12.2,2.9,12.2L2.9,12.2
C2.9,12.2,2.9,12.2,2.9,12.2 M3,12.1C3,12,3,12,3,12.1C3.1,12,3.1,12,3,12.1C3.1,12,3.1,12,3,12.1C3,12,3,12,3,12.1
C3,12.1,3,12.1,3,12.1C3,12,3,12.1,3,12.1 M9,13c0,0,0-0.2,0-0.2c0,0,0.1,0,0-0.1c0-0.2,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0-0.1,0-0.1,0c-0.1,0-0.1,0.1-0.2,0.1c0,0,0-0.1,0-0.1c0.1,0,0.2-0.1,0.2-0.1c-0.3-0.1-0.3-0.2-0.3-0.2
c0-0.1,0-0.3-0.1-0.3c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0
c0,0,0,0.1-0.1,0c0,0,0,0.1,0,0.1c0,0,0.1,0,0.1,0c0-0.1-0.1,0-0.1-0.1c0,0,0,0,0,0C8.4,12,8.4,12,8.3,12c0,0,0,0,0,0c0,0,0,0,0,0
c-0.1-0.1-0.1-0.1-0.2-0.2c0,0,0,0-0.1,0.1c0,0,0,0,0,0.1C8,11.9,8,12,8,12c0,0,0,0,0,0c0,0,0-0.1-0.1-0.1C7.9,12,7.9,12,7.8,12
c0,0,0,0,0,0c0-0.1-0.1,0-0.2,0c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0,0.2,0,0.2c0,0,0-0.1,0-0.1c0,0,0,0,0,0c-0.1,0-0.2-0.2-0.2-0.2
c0,0,0-0.1,0-0.1c0,0-0.1-0.1-0.1-0.1c-0.1,0-0.1,0-0.1,0c-0.1,0-0.1,0-0.2-0.1c0,0,0,0,0,0c0,0-0.1,0,0,0.1c0,0,0,0.1,0,0.1v0
c0,0,0,0,0,0c0,0,0,0.1,0,0.1l-0.1,0.1C6.9,12,7.1,12,7,12.2c0,0.1-0.1,0.4-0.3,0.5c0,0,0.1,0.3,0.1,0.3c0,0,0,0,0,0
c0,0,0.3-0.4,0.3-0.4c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0.1-0.1,0.1-0.1,0.2c0,0-0.1,0.1-0.1,0.1c0,0-0.1,0-0.1-0.1c0,0,0,0-0.1,0c0,0,0,0.1,0,0.1c0.3,0,0.5,0,0.8,0c0.5,0,1,0,1.5,0
c0,0-0.1-0.1-0.1-0.1C9,12.9,9,12.9,9,12.8 M9,11.3C9,11.2,9,11.2,9,11.3L9,11.3L9,11.3 M6.8,11.3L6.8,11.3c0,0,0,0-0.1,0
c0,0,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c-0.1,0.1-0.1,0.1-0.1,0.2c-0.1,0-0.1,0-0.1,0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0,0,0,0.1,0
c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C6.7,11.3,6.7,11.3,6.8,11.3C6.8,11.3,6.8,11.3,6.8,11.3 M7.3,10.8
C7.3,10.8,7.3,10.8,7.3,10.8C7.3,10.8,7.2,10.8,7.3,10.8c-0.2,0-0.2,0.1-0.1,0.1C7.1,10.9,7.2,11,7.3,10.8"/>
<path style="fill:#B3E710;" d="M9.6,13.4C9.6,13.4,9.6,13.4,9.6,13.4C9.6,13.4,9.6,13.4,9.6,13.4C9.6,13.4,9.6,13.3,9.6,13.4
L9.6,13.4C9.5,13.3,9.5,13.3,9.6,13.4C9.5,13.4,9.5,13.4,9.6,13.4c-0.1-0.1-0.1-0.1-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0
l0,0c0,0,0,0-0.1,0c0,0,0,0,0.1-0.1c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0-0.1,0c0,0,0,0-0.1,0.1c0-0.1,0-0.1,0.1-0.2c0,0-0.1,0-0.1,0C9,13,9,13,9,13.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0
c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0-0.1,0-0.1,0.1c0,0,0,0,0,0.1c0.1,0,0.1,0,0.2,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0
c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0-0.1,0.1-0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1-0.1,0.1-0.1c0,0,0,0,0,0l0,0c0,0,0,0,0,0.1
c0,0,0,0,0,0l0,0L9.6,13.4C9.5,13.4,9.5,13.5,9.6,13.4C9.6,13.5,9.6,13.5,9.6,13.4C9.6,13.5,9.6,13.4,9.6,13.4 M12.6,12.9
C12.6,12.9,12.6,12.9,12.6,12.9C12.6,12.9,12.6,12.9,12.6,12.9L12.6,12.9C12.6,12.9,12.6,12.9,12.6,12.9 M11.6,11.8
c0,0-0.1-0.2-0.2-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C11.7,11.9,11.7,11.9,11.6,11.8C11.6,11.9,11.6,11.9,11.6,11.8
M11.5,11.7L11.5,11.7C11.5,11.7,11.4,11.7,11.5,11.7C11.4,11.7,11.4,11.7,11.5,11.7C11.4,11.7,11.5,11.7,11.5,11.7 M11.8,11.7
C11.8,11.6,11.8,11.6,11.8,11.7L11.8,11.7C11.8,11.7,11.8,11.7,11.8,11.7C11.8,11.7,11.8,11.7,11.8,11.7
C11.8,11.7,11.8,11.7,11.8,11.7C11.9,11.7,11.9,11.7,11.8,11.7C11.9,11.7,11.9,11.7,11.8,11.7C11.9,11.7,11.9,11.7,11.8,11.7
C11.9,11.7,11.9,11.7,11.8,11.7L11.8,11.7L11.8,11.7C11.9,11.7,11.8,11.7,11.8,11.7 M11.6,11.4C11.6,11.4,11.6,11.4,11.6,11.4
L11.6,11.4C11.6,11.5,11.6,11.5,11.6,11.4C11.6,11.5,11.6,11.5,11.6,11.4c0.1,0.1,0.1,0.1,0.1,0.1C11.7,11.5,11.7,11.5,11.6,11.4
C11.6,11.5,11.6,11.5,11.6,11.4C11.6,11.5,11.6,11.5,11.6,11.4 M9.4,11.4C9.4,11.4,9.4,11.4,9.4,11.4C9.4,11.4,9.4,11.4,9.4,11.4
C9.4,11.4,9.4,11.4,9.4,11.4C9.4,11.4,9.3,11.4,9.4,11.4C9.3,11.4,9.4,11.4,9.4,11.4C9.4,11.4,9.4,11.4,9.4,11.4 M12.1,12.1
c0,0-0.1-0.1-0.1-0.1C12,12,12,12,12.1,12.1C11.9,12,11.9,12,11.9,12c0,0-0.1-0.1-0.2-0.2c-0.2-0.1-0.2-0.2-0.2-0.2c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1-0.1-0.1-0.1c0,0-0.1,0-0.1,0c0,0,0-0.1-0.1-0.1c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0.1,0.1c0,0,0.1,0.1,0.1,0.1l0,0
c0,0,0,0,0,0l0,0c0,0,0,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0.1,0.1,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0
c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0.1l0,0C11.9,12.1,11.9,12.1,12.1,12.1C12,12.2,12,12.2,12.1,12.1C12,12.2,12,12.2,12.1,12.1
C12,12.2,12,12.1,12.1,12.1C12,12.2,12,12.2,12,12.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0.1,0,0.1,0,0.1
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C12.1,12.2,12.1,12.2,12.1,12.1
C12.1,12.2,12.1,12.2,12.1,12.1C12.1,12.2,12.1,12.2,12.1,12.1C12.1,12.2,12.1,12.2,12.1,12.1C12.1,12.1,12.1,12.1,12.1,12.1
M9.9,10.7c0,0-0.1,0-0.1,0c0,0,0,0-0.1,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0
c0,0-0.1,0-0.1,0c0,0,0,0,0,0l0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c-0.1,0-0.1-0.1-0.2-0.1c0,0,0,0,0,0l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0.1,0l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0.1,0,0.1,0,0.1,0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0
c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C10,10.8,10,10.8,9.9,10.7C10,10.8,10,10.8,9.9,10.7C10,10.8,10,10.7,9.9,10.7
C10,10.7,10,10.7,9.9,10.7C10,10.7,9.9,10.7,9.9,10.7 M8.6,10.2C8.6,10.2,8.6,10.2,8.6,10.2C8.5,10.2,8.5,10.2,8.6,10.2
C8.6,10.2,8.6,10.2,8.6,10.2L8.6,10.2C8.7,10.2,8.6,10.2,8.6,10.2L8.6,10.2L8.6,10.2L8.6,10.2L8.6,10.2C8.6,10.2,8.6,10.2,8.6,10.2
M12.1,11.9C12.1,11.9,12,11.8,12.1,11.9L12.1,11.9C12,11.9,12.1,11.9,12.1,11.9c0,0-0.1-0.1-0.1-0.1l0,0l0,0h0
C12,11.8,12,11.9,12.1,11.9C12.1,11.9,12.1,11.9,12.1,11.9L12.1,11.9L12.1,11.9L12.1,11.9C12,11.8,12,11.8,12,11.8c0,0,0,0,0,0
c0,0-0.1-0.1-0.1-0.1l0,0c0,0,0,0-0.1-0.1l0,0l0,0l0,0c0,0,0,0-0.1,0c0,0,0,0,0.1,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0.1,0.1,0.1,0.1l0,0c0.1,0,0.1,0.1,0.2,0.2l0,0L12.1,11.9L12.1,11.9L12.1,11.9C12,11.9,12,11.9,12.1,11.9
C12,11.9,12,11.9,12.1,11.9C12.1,11.9,12,11.9,12.1,11.9C12.1,11.9,12.1,11.9,12.1,11.9L12.1,11.9L12.1,11.9L12.1,11.9
C12.1,11.9,12,11.9,12.1,11.9C12,11.9,12,11.9,12.1,11.9C12,11.9,12,11.9,12.1,11.9C12.1,11.9,12.1,11.9,12.1,11.9
C12.1,12,12.1,12,12.1,11.9L12.1,11.9C12,11.9,12,11.9,12.1,11.9C12,11.9,12,11.9,12.1,11.9C12,12,12.1,12,12.1,11.9
c0,0.1,0,0.1,0,0.2c0,0,0,0,0,0c0,0,0,0,0,0l0,0C12.1,12,12.1,12,12.1,11.9c0,0.1,0,0.1,0.1,0.3c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0.1l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0l0,0l0,0
c0,0,0,0,0.1,0.1c0.1,0.1,0.1,0.1,0.2,0.2c0.2,0,0.3,0,0.3,0l0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c-0.1-0.1-0.1-0.2-0.2-0.3C12.6,12.4,12.3,12.1,12.1,11.9 M10.5,10.7c-0.2-0.1-0.4-0.2-0.6-0.3l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0.1C10.4,10.7,10.5,10.7,10.5,10.7C10.5,10.8,10.5,10.8,10.5,10.7
c0.1,0.1,0.2,0.1,0.2,0.1l0,0c0,0,0.1,0,0.1,0.1c0,0,0,0,0,0l0,0h0l0,0h0c0,0,0,0,0,0l0,0h0l0,0l0,0c0,0,0,0,0.1,0c0,0,0,0,0,0
c0,0,0,0,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0.1l0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0.1,0.1,0.1,0.1l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0
c-0.1-0.1-0.1-0.1-0.2-0.2c0,0,0,0,0.1,0c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0l0,0c0,0,0.1,0.1,0.1,0.1c0,0,0.1,0.1,0.1,0.1l0,0l0,0l0,0
c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0-0.1-0.1l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0-0.1-0.1-0.1-0.1c-0.1-0.1-0.2-0.2-0.3-0.3
C11.1,11.1,10.8,10.9,10.5,10.7 M8.3,10.1L8.3,10.1C8.3,10.1,8.3,10.1,8.3,10.1L8.3,10.1L8.3,10.1C8.3,10.1,8.2,10.1,8.3,10.1
L8.3,10.1C8.2,10.1,8.3,10.1,8.3,10.1L8.3,10.1L8.3,10.1C8.3,10.1,8.3,10.1,8.3,10.1L8.3,10.1L8.3,10.1L8.3,10.1L8.3,10.1
C8.3,10.1,8.3,10.1,8.3,10.1C8.3,10.1,8.3,10.1,8.3,10.1L8.3,10.1C8.3,10.1,8.3,10.1,8.3,10.1 M8.2,10.1L8.2,10.1L8.2,10.1
C8.2,10.1,8.2,10.1,8.2,10.1C8.2,10.1,8.2,10.1,8.2,10.1C8.2,10.1,8.2,10.1,8.2,10.1C8.2,10.1,8.2,10.1,8.2,10.1L8.2,10.1
C8.2,10.1,8.2,10.1,8.2,10.1C8.2,10.1,8.2,10.1,8.2,10.1 M8.2,10.1C8.2,10.1,8.2,10.1,8.2,10.1L8.2,10.1L8.2,10.1L8.2,10.1
C8.1,10.1,8.1,10.1,8.2,10.1L8.2,10.1L8.2,10.1L8.2,10.1L8.2,10.1C8.2,10.1,8.2,10.1,8.2,10.1C8.2,10.1,8.2,10.1,8.2,10.1 M8,10
L8,10C7.9,10,7.9,10,8,10C7.9,10,8,10,8,10C8,10,8,10,8,10 M7.9,10C7.8,10,7.8,10,7.9,10C7.8,10,7.8,10,7.9,10L7.9,10
C7.8,10,7.9,10,7.9,10C7.9,10,7.9,10,7.9,10 M7.8,10L7.8,10C7.8,10,7.7,10,7.8,10C7.8,10,7.8,10,7.8,10C7.7,10,7.7,10,7.8,10
C7.7,10,7.7,10,7.8,10C7.8,10,7.8,10,7.8,10L7.8,10C7.8,10,7.8,10,7.8,10 M7.7,10L7.7,10L7.7,10C7.6,10,7.6,10,7.7,10
C7.6,10,7.6,10,7.7,10C7.6,10,7.6,10,7.7,10C7.6,10,7.7,10,7.7,10L7.7,10 M7.9,10c-0.1,0-0.2,0-0.2,0h0c0,0,0.1,0,0.1,0
C7.8,10,7.8,10,7.9,10 M7.6,10C7.6,10,7.5,10,7.6,10L7.6,10C7.6,10,7.6,10,7.6,10C7.6,10,7.6,10,7.6,10 M8,10L8,10L8,10L8,10L8,10
M9,10H8.7c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0.2,0,0.2,0.1C9,10.2,9,10,9,10H8.7l0,0.1c0,0,0,0,0,0
l0-0.1c0,0,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0.2,0.1,0.2,0.1c0,0,0.2,0.1,0.2,0.1v0c0,0-0.2-0.1-0.2-0.1c0,0-0.2-0.1-0.2-0.1h0
c0,0,0,0,0,0c0,0,0,0,0,0s0,0,0,0C8.5,10,9,10.1,9,10v0.1c-1,0-0.3,0-0.3,0c0,0-0.1-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1c0,0,0,0,0,0
c0,0,0.1,0,0.1,0l0,0h0l0,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0.1,0l0,0c0,0,0-0.1,0-0.1l0-0.1h0.2
C8.8,10,9,10.1,9,10L9,10H8.3c0,0-0.3,0.1-0.3,0.1v-0.1c0,0,0.5-0.1,0.5-0.1h0l0,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0-0.4,0-0.4,0v0.1l0,0l0,0v0l0,0l0,0l0,0l0.4,0h0l0,0h0c0,0-0.4,0-0.4,0l0,0v0.1v0l0,0v0v0l0,0c0,0,0.2-0.1,0.2-0.1
c0,0,0.2,0,0.2,0h0c0,0,0,0.1,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0-0.1,0h0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0V10h0.1l0,0l0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0-0.2,0-0.2,0v0v0l0,0v0l0,0v0v0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0v0v0v0h0h0c0,0,0,0,0,0h0
c0,0,0,0,0,0h0v0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0h0c0,0,0,0,0,0h0c0,0,0,0,0,0h0c0,0,0,0,0,0c0,0-0.1,0-0.1,0h0c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0h0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0h0h0c0,0,0,0,0,0c0,0,0,0,0,0
c0.5,0,1,0.5,1.4,1.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0-0.2,0-0.1c0,0,0-0.2,0-0.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.2,0,0.2
c0,0,0,0.1,0,0.1c0,0,0.1,0,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0l0,0l0,0h0c0,0,0,0,0,0h0c0,0,0,0,0,0c0,0-0.2,0-0.2,0c0,0-0.2,0-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0.2,0,0.2,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0c0,0-0.2,0-0.2,0c0,0-0.2,0-0.2,0c0,0,0-0.2,0-0.2
c0,0,0.5-0.2,0.5-0.2h0c0,0,0,0.2,0,0.2c0,0,0,0.1,0,0.1c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0.2,0,0.2,0c0,0,0,0,0,0c0,0-0.1,0-0.2,0c0,0,0.1,0,0,0
c0,0,0.1,0,0.1,0c0,0,0-0.4,0-0.4s-0.3,0-0.3,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.2,0,0.2c0,0,0-0.1,0-0.1c0,0,0-0.1,0-0.1h0l0,0.2
c0,0,0,0.1,0,0.1c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1-0.1
c0,0,0,0,0.1,0l0,0c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0.2,0,0.2,0c0,0-0.7,0,0.3,0v0c-1,0-0.3,0-0.3,0H9.6c0,0,0,0,0,0
c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0-0.5,0-0.5,0v0l0,0v0l0,0v0h0.2H9v0l0.3,0c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0L9,11v0
c0,0,0.4,0,0.4,0c0,0,0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0l0,0c0,0,0,0-0.1,0l0,0l0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0-0.1,0c0,0,0,0,0.1,0c0,0,0,0.1,0,0.1c0,0,0,0.1-0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.3-0.1-0.3-0.1v-0.1c0,0,0.1,0,0.1-0.1c0,0,0.1,0,0.1,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0-0.1,0-0.1,0c0,0-0.2,0-0.2,0c0,0,0,0,0,0c0,0,0.2,0.3,0.2,0.3h0c0,0,0-0.2,0-0.2c0,0,0.1,0.1,0.1,0.1c0,0,0,0.1,0,0.1
c0,0,0,0,0,0c0,0,0-0.2,0-0.2c0,0,0-0.1,0-0.1c0,0-0.1,0-0.1,0c0,0-0.2,0-0.2,0V11c0,0,0.2,0,0.2,0c0,0,0.1-0.2,0-0.2
c0,0,0-0.1,0-0.1c0,0,0-0.1,0.1,0c0,0,0,0.2,0,0.2l0,0.2c0,0,0,0,0,0c0,0,0-0.3,0-0.3l0-0.1l0-0.1c0,0,0-0.3,0-0.3C9,10.2,9,10,9,10
C9,10,9,10,9,10L9,10.2c0,0,0,0.1-0.1,0.1l0,0c0,0,0.1,0.1,0.1,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0l0,0c0,0-0.1,0-0.1,0c0,0,0.1,0,0.1,0c0,0,0-0.1,0-0.1V10H8.8H9v0.1
l0,0V10c0,0-0.1,0-0.1,0l0,0H9L9,10v0.2l-0.1,0c0,0-0.1-0.1-0.1-0.1c0,0-0.1-0.1-0.1-0.1"/>
<path style="fill:#B3E710;" d="M10.4,20.8c0,0,0.1-0.2,0.1-0.2c0,0-0.1,0-0.1,0c-0.1-0.2-0.1-0.2-0.1-0.2c0,0-0.1,0-0.1,0
c0,0-0.1-0.1-0.1-0.1c0,0-0.1,0-0.2,0.1c0,0,0.1-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0-0.1-0.1c-0.2,0.8-0.5,1.5-0.8,2
c0.1,0,0.1,0,0.1,0c0,0,0.1,0,0.1-0.1c0,0,0.1,0,0.1,0c0,0,0.1-0.1,0.1-0.1c0-0.1,0.2-0.1,0.2-0.2c0.1-0.1,0.1-0.1,0.2-0.2
c0-0.1,0.1-0.1,0.2-0.3c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1-0.1c0,0,0.1-0.1,0.1-0.1c0.1-0.1,0.1-0.1,0.2-0.1
C10.3,20.8,10.4,20.8,10.4,20.8 M12.8,20.3c0.1-0.1,0.1-0.2,0.2-0.3c0,0,0,0,0,0s0,0,0,0c0,0,0,0,0,0c-0.6,0.9-1.1,1.3-1.3,1.5
c0.2-0.2,0.4-0.3,0.6-0.5C12.3,20.9,12.6,20.6,12.8,20.3 M9.5,20.1C9.5,20.1,9.5,20.1,9.5,20.1C9.5,20.1,9.5,20.1,9.5,20.1
C9.5,20.1,9.5,20.1,9.5,20.1 M9.4,20C9.4,20,9.4,20,9.4,20c0,0-0.1,0-0.2,0c0,0,0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0s0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0.1C9.3,20.1,9.3,20.1,9.4,20C9.4,20.1,9.4,20.1,9.4,20 M8.1,18.8C8.1,18.8,8.1,18.8,8.1,18.8
C8.1,18.8,8.1,18.8,8.1,18.8C8.1,18.8,8.1,18.8,8.1,18.8C8.1,18.8,8.1,18.8,8.1,18.8C8.1,18.8,8.1,18.9,8.1,18.8
C8.1,18.9,8.1,18.9,8.1,18.8C8.1,18.9,8,18.9,8,18.9c0,0,0,0,0,0C8.1,18.9,8.1,18.9,8.1,18.8C8.1,18.9,8.1,18.9,8.1,18.8 M6.8,17.4
L6.8,17.4c0-0.1-0.2-0.1-0.2-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0h0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0h0l0,0
c0,0,0.1,0.1,0.1,0.1C6.7,17.5,6.7,17.4,6.8,17.4C6.8,17.4,6.8,17.4,6.8,17.4C6.8,17.4,6.8,17.4,6.8,17.4
C6.8,17.4,6.8,17.4,6.8,17.4L6.8,17.4 M8.2,17.4C8.2,17.4,8.2,17.4,8.2,17.4c0,0-0.1-0.1-0.2,0c0,0,0,0,0,0.1
C8.1,17.4,8.2,17.4,8.2,17.4C8.2,17.4,8.2,17.4,8.2,17.4 M7.9,17.4C7.9,17.4,7.9,17.4,7.9,17.4c-0.1-0.1-0.2-0.1-0.2-0.1
c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0s0,0-0.1,0c0,0,0,0-0.1,0c-0.1,0-0.1,0-0.2,0l0,0c0,0,0,0,0,0
c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0,0,0,0,0c-0.1,0-0.2,0-0.3,0c0,0,0,0,0,0l0,0c0,0,0,0,0.1,0.1c0,0,0,0,0,0
c0,0,0,0,0.1,0c0.1,0,0.1,0,0.2,0c0,0,0,0.1,0.1,0.1c0-0.1,0-0.1,0.1-0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0
C7.8,17.4,7.8,17.4,7.9,17.4C7.8,17.4,7.8,17.4,7.9,17.4C7.9,17.4,7.9,17.4,7.9,17.4 M7.1,17.1L7.1,17.1C7,17.1,7,17.1,6.9,17.1
c0,0,0,0,0,0c0,0,0,0,0,0h0h0h0h0h0h0l0,0l0,0c-0.1,0-0.2,0-0.2-0.1c0,0,0-0.1-0.1-0.1c0,0-0.1,0-0.1,0c-0.1,0-0.1,0-0.2-0.1
c0,0,0,0,0,0c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0h0c0,0,0,0,0,0c0,0,0,0,0,0h0c0,0,0,0,0,0h0c0,0,0,0,0,0c-0.1,0-0.3,0-0.3,0.1
c0,0,0,0,0,0l0,0c0,0,0.1,0,0.1,0c0.2-0.1,0.2-0.1,0.3-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0.1,0,0.1,0,0.2,0c0.1,0,0.1,0,0.1,0.1c0,0,0,0,0,0c0.1,0,0.1,0,0.1,0.1c0.1,0,0.1,0,0.2,0.1c0,0,0,0.1-0.1,0.1
c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0.1,0,0.1,0,0.2,0C7,17.2,7.1,17.2,7.1,17.1 M7,15L7,15C7,15,6.9,14.9,7,15C6.9,14.9,6.9,14.9,7,15
C6.9,15,7,15,7,15 M6.9,14.9C6.9,14.9,6.9,14.9,6.9,14.9L6.9,14.9L6.9,14.9 M6.9,14.9C6.9,14.9,6.9,14.9,6.9,14.9L6.9,14.9
C6.9,14.9,6.9,14.9,6.9,14.9 M6.9,14.9C6.9,14.9,6.9,14.9,6.9,14.9L6.9,14.9C6.9,14.9,6.9,14.9,6.9,14.9 M6.9,14.9
C6.9,14.9,6.9,14.9,6.9,14.9L6.9,14.9C6.9,14.9,6.9,14.9,6.9,14.9 M8.9,13.6C8.9,13.6,8.9,13.6,8.9,13.6C8.9,13.6,8.8,13.5,8.9,13.6
c-0.1,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0.1-0.1,0.1c0,0,0,0,0,0.1
C8.7,13.6,8.8,13.6,8.9,13.6C8.8,13.6,8.9,13.6,8.9,13.6 M2.7,13.3L2.7,13.3C2.7,13.2,2.7,13.2,2.7,13.3C2.7,13.2,2.7,13.2,2.7,13.3
c0-0.1,0-0.1,0-0.1c0,0,0-0.1,0-0.1c0,0,0,0,0,0c0,0,0,0-0.1,0c0,0,0,0,0,0l0,0c0,0,0,0.1,0,0.1c0,0,0,0,0,0c0,0,0,0,0,0.1l0,0
c0,0,0,0,0,0C2.6,13.2,2.6,13.2,2.7,13.3C2.6,13.2,2.6,13.2,2.7,13.3C2.7,13.2,2.6,13.2,2.7,13.3C2.6,13.2,2.6,13.2,2.7,13.3
C2.6,13.2,2.7,13.3,2.7,13.3C2.7,13.3,2.7,13.3,2.7,13.3C2.7,13.3,2.7,13.3,2.7,13.3 M9.3,19.8C9.3,19.8,9.3,19.8,9.3,19.8
c-0.1-0.1-0.1-0.1-0.1-0.3c0,0-0.4-0.3-0.5-0.2c0,0-0.1,0-0.1,0c0,0,0,0,0,0l0,0c-0.1-0.1-0.3-0.1-0.4-0.1c0,0-0.3,0-0.3,0
c0,0,0,0,0,0c0-0.2,0.1-0.2-0.1-0.2c0,0,0.1,0,0.1,0C8,19,8.1,19,8.1,19c-0.1,0,0,0-0.1-0.1c0,0,0,0-0.1,0c0,0,0,0,0,0
c0,0,0,0,0-0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0l0,0l0,0c-0.2,0-0.3,0-0.5,0c-0.1,0-0.3-0.1-0.4-0.1c0,0,0-0.1,0-0.1c0,0,0,0,0,0
c0,0,0,0,0,0l0,0l0,0c0,0,0,0-0.2,0.1c0,0,0,0,0,0c0,0.1,0.1,0.1,0.1,0.2c0,0,0,0-0.1,0c-0.1-0.1-0.1-0.1,0-0.2c0-0.1,0-0.1,0-0.1
c0,0,0.1,0,0.1,0c0,0,0.1,0,0.1,0c0,0-0.1,0-0.1,0c0,0,0,0,0,0c0,0-0.3,0.3-0.3,0.3c0,0,0,0,0,0c0,0,0-0.3-0.2-0.4
c-0.1,0-0.2,0-0.3,0C6,18.5,5.8,18.2,5.9,18c0,0,0-0.1,0-0.2c0,0-0.1,0-0.1,0c0-0.1-0.2,0-0.2-0.1c-0.1,0-0.3,0-0.3,0c0,0,0,0,0,0
l0,0l0,0c0.1-0.1,0.1-0.1,0.1-0.3c0,0,0,0,0-0.1l0,0c0,0,0,0,0-0.1l0,0c0,0,0,0,0,0.1c0-0.1,0-0.1,0-0.2c0,0,0,0,0,0l0,0l0-0.1
C5.5,17,5.5,17,5.5,17c-0.2-0.1-0.3,0-0.4,0c-0.1,0,0,0-0.1,0c0,0.1,0,0-0.1,0c0,0,0,0,0,0c0,0,0,0.2,0,0.2c0,0,0,0.1,0,0.1
c0,0,0,0,0,0c0,0,0,0,0,0c-0.1,0-0.3,0-0.4,0C4.2,17,4.2,17,4.2,16.9c0-0.3,0.1-0.8,0.1-0.8l0-0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0
c0,0,0,0,0,0c0.1,0,0.1,0,0.2-0.1c0,0,0,0,0-0.1l0,0.1c0.1,0,0.2,0.1,0.3,0.1c0,0,0,0,0,0l0-0.1l0,0l0,0c0,0,0.1,0.1,0.1,0.1
C5,16,5.1,16,5.1,16c0,0,0,0,0,0L5,15.9c0,0,0,0,0,0l0.1,0l0,0l0,0c0,0,0.1,0.1,0.1,0.1c0,0,0,0-0.1-0.1c0,0,0,0,0,0c0,0,0,0-0.1,0
c0,0,0,0,0,0c0,0,0,0,0.1,0c0.1,0,0.1,0,0.2,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0.1,0.1c0,0,0,0,0,0c0.1,0,0.1,0,0.1,0
c0.2,0.1,0.2,0.1,0.2,0.1c0,0,0,0,0.2,0.1C6,16,6,16,6,16.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1,0,0.1
c0,0,0,0,0,0c0,0,0,0,0,0.1c0,0.1,0.1,0.1,0.1,0.2c0,0,0.1-0.3,0.1-0.3c0,0,0-0.2,0-0.2c0,0,0,0,0,0c0.1,0-0.2-0.3-0.1-0.6
c0.1-0.2,0.4-0.2,0.6-0.4l0,0.1l0,0l0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1,0c0,0,0.1,0,0.1,0
c0,0,0.1,0,0.1,0v0l-0.1,0l0,0l0,0l0.1,0l0,0v0l0,0c0,0,0,0.1,0,0.1c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0,0,0,0l0,0l0,0l0,0.1
c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0-0.1-0.1-0.1-0.1l0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0,0,0,0,0l0,0
l0,0c0,0,0,0,0,0l0-0.1c0,0,0-0.1-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0-0.1,0-0.1-0.1c0,0,0.1,0,0.1,0l0.1,0c0,0,0,0.4,0,0.4
s-0.2,0-0.2,0c0,0,0-0.2,0-0.2c0,0,0-0.1,0-0.1c0,0,0,0.2,0.1,0.2c0,0,0,0.1,0,0.1c0,0,0,0,0,0h0c0,0,0,0,0,0c0,0,0-0.3,0-0.3
c0,0,0-0.1,0-0.1l0,0.2l0,0.2c0,0,0,0,0,0l0-0.3l0-0.1l0-0.1l0,0.2l0,0.3h0l0-0.2l0-0.2c0,0,0,0.5,0,0.5s-0.1,0-0.1,0l0-0.2l0.1-0.1
l0-0.1c0,0,0,0,0,0l0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0l0,0l0,0l0,0l0,0c0,0,0,0.3,0,0.3s0,0,0,0
c0,0,0,0,0,0c0,0,0-0.1,0,0l0-0.1c0,0,0-0.1,0-0.1C7,14.7,7,14.4,7,14.3c0,0,0-0.3,0-0.3h0l0,0.5C7,14.5,7,15,7,15c0,0-0.1,0-0.1,0
s0-0.4,0-0.4l0,0c0,0,0.1-0.1,0.1-0.1c0-0.1,0.1-0.1,0-0.2l0,0c0,0,0,0,0,0c0.1,0,0.2-0.1,0.3-0.1c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.2,0,0.2,0c0,0,0.1,0,0.1,0c0,0,0,0,0,0L7.7,14
c0,0,0.3,0,0.3,0s0,0.2,0,0.2l-0.2,0l-0.1,0c0,0-0.1-0.1-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0-0.1,0.2-0.1,0.2-0.1
c0,0,0,0,0,0l-0.1,0l-0.1,0.1L7.7,14c0,0,0,0,0,0l0-0.1l0,0l0,0l0,0l0,0c0,0,0,0.1,0,0c0,0,0,0.1,0,0.1h0l0-0.1l0,0l0,0l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1,0.1,0.1c0,0,0,0.1,0,0.1c0,0,0,0,0,0l0-0.1l0-0.1l0,0c0,0,0.1,0,0.1,0
c0,0,0,0,0,0l0,0c0,0,0.1,0,0.1-0.1l0,0.2l0,0.2c0,0,0,0,0,0c0,0,0-0.2-0.1-0.1c0,0,0-0.1,0-0.1c0.1,0,0.2-0.1,0.2-0.1
c0,0-0.1,0-0.1,0c0,0-0.2,0-0.2,0l-0.2,0V14h0.2l0,0l0,0c0,0,0.1,0,0.1,0l0,0l0,0l0,0l0,0c0,0,0,0-0.1,0c0,0,0,0,0,0L8,13.8
c0,0,0,0,0,0l0.1,0c0,0,0,0,0,0l0,0l0,0c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0
c0,0,0.1-0.1,0.1-0.1c0,0,0,0.1,0,0.1l0,0.1c0,0,0,0,0,0l-0.2-0.1L8,13.8v0c0,0,0.3,0,0.3,0l0.1,0l0.1,0l0,0c0.1,0,0.1,0,0.2-0.1
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0l0,0l0,0c0,0,0,0-0.1,0l0,0l0,0l0,0c0,0-0.1,0-0.1,0c0,0,0,0.2-0.1,0.2c0,0,0,0.2,0,0.2
c0,0,0,0,0,0l0-0.2c0,0-0.1-0.1-0.1-0.1l0,0.2c0,0,0,0.1,0,0.1c0,0,0,0,0,0S8,14,8,14s0-0.4,0-0.4l0.2,0l-0.1,0
c-0.1,0-0.2,0-0.2-0.1c0,0,0,0,0,0c0,0,0.1,0,0.1,0c0,0,0.1-0.1,0.1-0.1l-0.1,0l-0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0-0.1,0.3-0.1,0.3-0.1c-0.2-0.2-0.6,0.1-0.7,0.3C7.8,13,8.2,13,8.6,13c0.1,0,0.2,0,0.3,0c-0.5,0-1,0-1.5,0c-0.3,0-0.5,0-0.8,0
c-1.7,0-3.1,0-3.9,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.3-0.1,0.4c0,0,0,0,0,0c0,0,0,0,0-0.1c0,0,0,0,0,0
c0,0-0.1,0-0.1,0c0,0,0,0.1,0,0.1c0,0,0,0,0,0l0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0.1-0.1,0.2-0.2,0.4c0,0.1,0,0.1-0.2,0.6c0,0,0,0,0,0c0,0,0,0,0,0l0,0.1l0,0
c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1,0,0.1c0,0,0,0,0,0l0,0c0,0.1,0.1,0.3,0,0.4c0,0,0.1,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0l0,0
c0,0,0.3,0,0.3,0c0,0.1-0.7,0.1,0.3,0.2c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c-1,0-1,0-1,0c0,0,0,0,0,0
c0,0,0,0,0,0c1,0,0.4,0.6,0.4,0.6c0,0,0.1,0,0.1,0c0,0,0.3,0.5,0.5,0.7c0,0,0.1-0.1,0.1-0.1c0,0,0,0,0-0.1c0,0,0,0,0,0
c0-0.1-0.1-0.4-0.1-0.4c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0,0,0,0c0-0.2-0.1-0.3-0.2-0.5c0,0,0-0.1,0-0.1c0,0,0.1,0,0.1,0l0,0
c0,0,0,0,0,0c0,0,0,0,0,0C2.8,16,2.8,16,3.1,16.3c0,0.1,0,0.1,0,0.1l0,0c0.1,0.2,0.2,0.3,0.3,0.5c0,0,0,0,0,0c0,0.1,0,0.1,0,0.2
c0,0,0,0,0,0c0,0,0,0,0,0C3.5,17.3,4,17.6,4,17.6c0.1,0,0.2,0.1,0.3,0.1c0.1,0,0.2-0.1,0.4,0c0.2,0.1,0.2,0.2,0.4,0.3L5.4,18
c0,0,0,0,0-0.1c0,0,0,0,0.1,0c0,0,0,0,0,0c0,0,0,0,0,0c0.1,0.1,0.2,0.2,0.3,0.2l0,0l0,0l0,0c0,0,0,0,0,0c0,0,0,0.1,0.1,0.1l0.1,0
c0,0,0.1,0,0.1-0.1c0,0,0,0,0,0c0,0,0.1,0.1,0.1,0.1c0,0-0.1,0-0.1,0c0,0,0,0,0,0l-0.1,0v0.2C6,18.8,6,19,6,19c0,0,0,0,0,0
c0.1,0,0.1,0,0.2,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0-0.1,0-0.1c0,0,0.1-0.1,0.1-0.1c0,0-0.2-0.1-0.2-0.1c0,0-0.2-0.1-0.2-0.1
c0,0,0,0,0,0c0,0,0.2,0,0.3,0c0,0,0.1,0,0.1,0c0.1,0,0.2,0,0.2,0.1c0,0,0.1,0.2,0.1,0.2c0,0,0,0.2,0.1,0.2c0,0,0,0,0,0
c0,0,0-0.1,0-0.1c0,0-0.1-0.1-0.2-0.1c0,0,0,0,0,0c0,0,0,0,0-0.1c-0.2,0-0.1,0.2-0.2,0.3c0,0,0,0,0,0c0,0,0,0,0,0l0,0
c0,0,0,0-0.1-0.1c0,0,0,0,0,0c0,0,0,0.1,0,0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1,0,0.1c0.1,0.1,0.1,0.3,0.1,0.3c0,0,0,0,0,0
c0,0,0,0,0,0.1c0,0-0.1,0-0.1,0c0,0,0,0,0,0.1c0,0,0,0,0,0c0,0-0.1,0-0.1,0.1c0,0,0,0,0,0.1c0.4,0,0.9,0,1.4,0c0.6,0,1.2,0,1.7,0
C9.1,20,9.3,19.9,9.3,19.8"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="7.4653" y1="9.0342" x2="7.4653" y2="23.9663">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_8_);" d="M7.5,9C3.3,9,0,12.4,0,16.5C0,20.6,3.3,24,7.5,24c4.1,0,7.5-3.3,7.5-7.5
C14.9,12.4,11.6,9,7.5,9z M13.7,18.6c-0.1,0.3-0.2,0.6-0.4,0.9s-0.3,0.6-0.5,0.9s-0.4,0.5-0.6,0.8s-0.5,0.5-0.8,0.6
c-0.3,0.2-0.6,0.4-0.9,0.5c-0.3,0.2-0.6,0.3-0.9,0.4s-0.7,0.2-1,0.2C8.2,23,7.9,23,7.5,23C1,22.7-0.9,15.2,3.3,11.6
C5,10.1,6.8,10,7.5,10c0.4,0,0.7,0,1.1,0.1c0.3,0.1,0.7,0.1,1,0.2s0.6,0.2,0.9,0.4c0.3,0.2,0.6,0.3,0.9,0.5c0.3,0.2,0.5,0.4,0.8,0.6
c0.2,0.2,0.5,0.5,0.6,0.8c0.2,0.3,0.4,0.6,0.5,0.9s0.3,0.6,0.4,0.9s0.2,0.7,0.2,1c0.1,0.3,0.1,0.7,0.1,1.1c0,0.4,0,0.7-0.1,1.1
C13.9,17.9,13.8,18.2,13.7,18.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -0,0 +1,228 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="18" y1="13" x2="18" y2="20.0005">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="12" y="13" style="fill:url(#SVGID_1_);" width="12" height="7"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="17.5" y1="14" x2="17.5" y2="19">
<stop offset="0" style="stop-color:#F7F7F7"/>
<stop offset="0.1044" style="stop-color:#FCFCFC"/>
<stop offset="0.3293" style="stop-color:#FFFFFF"/>
<stop offset="0.5692" style="stop-color:#E8E8E8"/>
<stop offset="0.8153" style="stop-color:#D7D7D7"/>
<stop offset="1" style="stop-color:#D1D1D1"/>
<a:midPointStop offset="0" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.2222" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.3293" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0.3545" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="1" style="stop-color:#D1D1D1"/>
</linearGradient>
<rect x="12" y="14" style="fill:url(#SVGID_2_);" width="11" height="5"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="17" y1="15" x2="17" y2="18">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="12" y="15" style="fill:url(#SVGID_3_);" width="10" height="3"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="16.5" y1="0" x2="16.5" y2="24.0005">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="13" style="fill:url(#SVGID_4_);" width="7" height="24"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="16.5" y1="1" x2="16.5" y2="23.0005">
<stop offset="0" style="stop-color:#F7F7F7"/>
<stop offset="0.1044" style="stop-color:#FCFCFC"/>
<stop offset="0.3293" style="stop-color:#FFFFFF"/>
<stop offset="0.5692" style="stop-color:#E8E8E8"/>
<stop offset="0.8153" style="stop-color:#D7D7D7"/>
<stop offset="1" style="stop-color:#D1D1D1"/>
<a:midPointStop offset="0" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.2222" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.3293" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0.3545" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="1" style="stop-color:#D1D1D1"/>
</linearGradient>
<rect x="14" y="1" style="fill:url(#SVGID_5_);" width="5" height="22"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="16.5" y1="2" x2="16.5" y2="22.0005">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="15" y="2" style="fill:url(#SVGID_6_);" width="3" height="20"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="18" y1="4" x2="18" y2="11">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="12" y="4" style="fill:url(#SVGID_7_);" width="12" height="7"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="17.5" y1="5" x2="17.5" y2="10">
<stop offset="0" style="stop-color:#F7F7F7"/>
<stop offset="0.1044" style="stop-color:#FCFCFC"/>
<stop offset="0.3293" style="stop-color:#FFFFFF"/>
<stop offset="0.5692" style="stop-color:#E8E8E8"/>
<stop offset="0.8153" style="stop-color:#D7D7D7"/>
<stop offset="1" style="stop-color:#D1D1D1"/>
<a:midPointStop offset="0" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.2222" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.3293" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0.3545" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="1" style="stop-color:#D1D1D1"/>
</linearGradient>
<rect x="12" y="5" style="fill:url(#SVGID_8_);" width="11" height="5"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="17" y1="6" x2="17" y2="9">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="12" y="6" style="fill:url(#SVGID_9_);" width="10" height="3"/>
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="6" y1="4" x2="6" y2="11">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect y="4" style="fill:url(#SVGID_10_);" width="12" height="7"/>
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="6.5" y1="5" x2="6.5" y2="10">
<stop offset="0" style="stop-color:#F7F7F7"/>
<stop offset="0.1044" style="stop-color:#FCFCFC"/>
<stop offset="0.3293" style="stop-color:#FFFFFF"/>
<stop offset="0.5692" style="stop-color:#E8E8E8"/>
<stop offset="0.8153" style="stop-color:#D7D7D7"/>
<stop offset="1" style="stop-color:#D1D1D1"/>
<a:midPointStop offset="0" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.2222" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.3293" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0.3545" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="1" style="stop-color:#D1D1D1"/>
</linearGradient>
<rect x="1" y="5" style="fill:url(#SVGID_11_);" width="11" height="5"/>
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="7" y1="6" x2="7" y2="9">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="2" y="6" style="fill:url(#SVGID_12_);" width="10" height="3"/>
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="7.5" y1="0" x2="7.5" y2="24.0005">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="4" style="fill:url(#SVGID_13_);" width="7" height="24"/>
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="7.5" y1="1" x2="7.5" y2="23.0005">
<stop offset="0" style="stop-color:#F7F7F7"/>
<stop offset="0.1044" style="stop-color:#FCFCFC"/>
<stop offset="0.3293" style="stop-color:#FFFFFF"/>
<stop offset="0.5692" style="stop-color:#E8E8E8"/>
<stop offset="0.8153" style="stop-color:#D7D7D7"/>
<stop offset="1" style="stop-color:#D1D1D1"/>
<a:midPointStop offset="0" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.2222" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.3293" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0.3545" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="1" style="stop-color:#D1D1D1"/>
</linearGradient>
<rect x="5" y="1" style="fill:url(#SVGID_14_);" width="5" height="22"/>
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="7.5" y1="2" x2="7.5" y2="22.0005">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="6" y="2" style="fill:url(#SVGID_15_);" width="3" height="20"/>
<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="6" y1="13" x2="6" y2="20.0005">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect y="13" style="fill:url(#SVGID_16_);" width="12" height="7"/>
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="6.5" y1="14" x2="6.5" y2="19">
<stop offset="0" style="stop-color:#F7F7F7"/>
<stop offset="0.1044" style="stop-color:#FCFCFC"/>
<stop offset="0.3293" style="stop-color:#FFFFFF"/>
<stop offset="0.5692" style="stop-color:#E8E8E8"/>
<stop offset="0.8153" style="stop-color:#D7D7D7"/>
<stop offset="1" style="stop-color:#D1D1D1"/>
<a:midPointStop offset="0" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.2222" style="stop-color:#F7F7F7"/>
<a:midPointStop offset="0.3293" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="0.3545" style="stop-color:#FFFFFF"/>
<a:midPointStop offset="1" style="stop-color:#D1D1D1"/>
</linearGradient>
<rect x="1" y="14" style="fill:url(#SVGID_17_);" width="11" height="5"/>
<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="7" y1="15" x2="7" y2="18">
<stop offset="0" style="stop-color:#8E8E8E"/>
<stop offset="4.191053e-02" style="stop-color:#8A8A8A"/>
<stop offset="0.4613" style="stop-color:#626262"/>
<stop offset="0.7952" style="stop-color:#4A4A4A"/>
<stop offset="1" style="stop-color:#414141"/>
<a:midPointStop offset="0" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="0.4" style="stop-color:#8E8E8E"/>
<a:midPointStop offset="1" style="stop-color:#414141"/>
</linearGradient>
<rect x="2" y="15" style="fill:url(#SVGID_18_);" width="10" height="3"/>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" style="overflow:visible;enable-background:new 0 0 24 24;"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<defs>
</defs>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="7.9995" y1="7.9868" x2="7.9995" y2="24.001">
<stop offset="0" style="stop-color:#F0A829"/>
<stop offset="1" style="stop-color:#C7671A"/>
<a:midPointStop offset="0" style="stop-color:#F0A829"/>
<a:midPointStop offset="0.5" style="stop-color:#F0A829"/>
<a:midPointStop offset="1" style="stop-color:#C7671A"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M3,19.2l-3,1.6V24h16v-0.4c0-0.5-0.5-1.2-1-1.5l-6-3.1c-0.5-0.3-0.6-0.8-0.3-1.2
c0,0,1.6-2,1.6-4.2C10.4,10.5,8.4,8,6,8c-2.4,0-4.4,2.6-4.4,5.7c0,2.1,1.6,4.2,1.6,4.2C3.6,18.3,3.5,18.9,3,19.2z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="7.7212" y1="8.9868" x2="7.7212" y2="23.001">
<stop offset="0" style="stop-color:#FFEBA8"/>
<stop offset="1" style="stop-color:#F8BE27"/>
<a:midPointStop offset="0" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="0.5" style="stop-color:#FFEBA8"/>
<a:midPointStop offset="1" style="stop-color:#F8BE27"/>
</linearGradient>
<path style="fill:url(#SVGID_2_);" d="M1,23v-1.7L3.5,20c0.5-0.3,0.8-0.7,1-1.2c0.1-0.5,0-1.1-0.4-1.5c0,0-1.4-1.8-1.4-3.6
C2.6,11.1,4.2,9,6,9s3.4,2.1,3.4,4.7c0,1.7-1.4,3.5-1.4,3.6c-0.3,0.4-0.5,1-0.4,1.5c0.1,0.5,0.5,1,1,1.2l5.9,3H1z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="6.1343" y1="9.9868" x2="6.1343" y2="22.001">
<stop offset="0" style="stop-color:#FFC30F"/>
<stop offset="1" style="stop-color:#F5AE0D"/>
<a:midPointStop offset="0" style="stop-color:#FFC30F"/>
<a:midPointStop offset="0.5" style="stop-color:#FFC30F"/>
<a:midPointStop offset="1" style="stop-color:#F5AE0D"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M2,22L2,22l1.9-1.1c0.8-0.4,1.3-1.1,1.5-1.9c0.2-0.8,0-1.7-0.6-2.3c-0.3-0.4-1.2-1.8-1.2-3
c0-2,1.1-3.7,2.4-3.7s2.4,1.7,2.4,3.7c0,1.1-0.9,2.5-1.2,3c-0.5,0.7-0.7,1.5-0.5,2.3c0.2,0.8,0.7,1.5,1.5,1.9l2.2,1.1H2z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="16" y1="7.9868" x2="16" y2="24.001">
<stop offset="0" style="stop-color:#8D470D"/>
<stop offset="1" style="stop-color:#7C3D09"/>
<a:midPointStop offset="0" style="stop-color:#8D470D"/>
<a:midPointStop offset="0.5" style="stop-color:#8D470D"/>
<a:midPointStop offset="1" style="stop-color:#7C3D09"/>
</linearGradient>
<path style="fill:url(#SVGID_4_);" d="M24,24v-3.4l-3-1.5c-0.5-0.3-0.6-0.8-0.3-1.2c0,0,1.6-2,1.6-4.2c0-3.2-1.9-5.7-4.4-5.7
c-2.4,0-4.4,2.6-4.4,5.7c0,2.1,1.6,4.2,1.6,4.2c0.3,0.4,0.2,1-0.3,1.3l-6,3.2c-0.5,0.3-1,0.9-1,1.5V24H24z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="16.4121" y1="8.9868" x2="16.4121" y2="23.001">
<stop offset="0" style="stop-color:#D58738"/>
<stop offset="1" style="stop-color:#AB551F"/>
<a:midPointStop offset="0" style="stop-color:#D58738"/>
<a:midPointStop offset="0.5" style="stop-color:#D58738"/>
<a:midPointStop offset="1" style="stop-color:#AB551F"/>
</linearGradient>
<path style="fill:url(#SVGID_5_);" d="M9.8,23l5.7-3c0.5-0.3,0.8-0.7,1-1.2c0.1-0.5,0-1.1-0.4-1.5c0,0-1.4-1.8-1.4-3.6
c0-2.6,1.5-4.7,3.4-4.7s3.4,2.1,3.4,4.7c0,1.8-1.4,3.6-1.4,3.6c-0.3,0.4-0.5,1-0.4,1.5s0.5,1,1,1.2l2.4,1.2V23H9.8z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="17.9424" y1="9.9868" x2="17.9424" y2="22.001">
<stop offset="0" style="stop-color:#D0813A"/>
<stop offset="1" style="stop-color:#AF551D"/>
<a:midPointStop offset="0" style="stop-color:#D0813A"/>
<a:midPointStop offset="0.5" style="stop-color:#D0813A"/>
<a:midPointStop offset="1" style="stop-color:#AF551D"/>
</linearGradient>
<path style="fill:url(#SVGID_6_);" d="M13.9,22l2.1-1.1c0.8-0.4,1.3-1.1,1.5-1.9c0.2-0.8,0-1.7-0.6-2.3c-0.3-0.4-1.2-1.8-1.2-3
c0-2,1.1-3.7,2.4-3.7s2.4,1.7,2.4,3.7c0,1.2-0.9,2.5-1.2,3c-0.5,0.7-0.7,1.5-0.6,2.3c0.2,0.8,0.7,1.5,1.5,1.9l1.9,1V22H13.9z"/>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="7.4507" y1="0" x2="7.4507" y2="12.9043">
<stop offset="0" style="stop-color:#76A1F0"/>
<stop offset="1" style="stop-color:#6B90D5"/>
<a:midPointStop offset="0" style="stop-color:#76A1F0"/>
<a:midPointStop offset="0.5" style="stop-color:#76A1F0"/>
<a:midPointStop offset="1" style="stop-color:#6B90D5"/>
</linearGradient>
<path style="fill:url(#SVGID_7_);" d="M12.5,10.4c1.4-1.1,2.4-2.6,2.4-4.3c0.1-3.3-3.2-6-7.3-6.1C3.4-0.1,0.1,2.5,0,5.8
c-0.1,3.3,3.2,6,7.3,6.1c1,0,2-0.1,2.9-0.4c0.8,1,2.8,1.4,2.8,1.4S12.2,11.7,12.5,10.4z"/>
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="7.4507" y1="1" x2="7.4507" y2="11.2168">
<stop offset="0" style="stop-color:#BBE0F7"/>
<stop offset="1" style="stop-color:#82B4FB"/>
<a:midPointStop offset="0" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="0.5" style="stop-color:#BBE0F7"/>
<a:midPointStop offset="1" style="stop-color:#82B4FB"/>
</linearGradient>
<path style="fill:url(#SVGID_8_);" d="M11.4,11.2c-0.2-0.1-0.3-0.2-0.4-0.3l-0.4-0.6l-0.7,0.2c-0.8,0.2-1.6,0.4-2.4,0.4l-0.1,0
C3.8,10.8,1,8.6,1,5.8C1,3.2,3.9,1,7.4,1l0.2,0c1.8,0,3.4,0.6,4.6,1.6c1.1,1,1.8,2.2,1.7,3.5c0,1.3-0.7,2.6-2,3.5l-0.3,0.2l-0.1,0.4
C11.4,10.5,11.4,10.9,11.4,11.2z"/>
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="7.4507" y1="2" x2="7.4507" y2="9.9097">
<stop offset="0" style="stop-color:#95BFF8"/>
<stop offset="0.5569" style="stop-color:#84ADEF"/>
<stop offset="1" style="stop-color:#7CA4EB"/>
<a:midPointStop offset="0" style="stop-color:#95BFF8"/>
<a:midPointStop offset="0.4" style="stop-color:#95BFF8"/>
<a:midPointStop offset="1" style="stop-color:#7CA4EB"/>
</linearGradient>
<path style="fill:url(#SVGID_9_);" d="M7.4,9.9C4.4,9.9,2,8,2,5.9C2,3.8,4.5,2,7.4,2l0.1,0c1.5,0,2.9,0.5,4,1.4
c0.9,0.8,1.4,1.7,1.4,2.7c0,1-0.6,2-1.6,2.7l-0.6,0.4l0,0.1L9.6,9.6C9,9.8,8.2,9.9,7.5,9.9L7.4,9.9z"/>
<path style="fill:#FFFFFF;" d="M5.5,4.5h1.9V6c0,0.5-0.1,1-0.3,1.3C6.9,7.6,6.5,7.9,5.9,8.1L5.5,7.3C5.9,7.2,6.1,7,6.2,6.9
c0.1-0.2,0.2-0.3,0.2-0.6H5.5V4.5z M7.7,4.5h1.9V6c0,0.5-0.1,1-0.3,1.3C9.1,7.6,8.7,7.9,8.2,8.1L7.7,7.3C8.1,7.2,8.3,7,8.4,6.9
c0.1-0.2,0.2-0.3,0.2-0.6H7.7V4.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,99 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* A cache to store values in memory to speed up processes.
*
* The data is organized by "entries" that are identified by an ID. Each entry can have multiple values stored,
* and each value has its own timemodified.
*
* Values expire after a certain time.
*/
export class CoreCache {
protected cacheStore = {};
constructor() {}
/**
* Clear the cache.
*/
clear() {
this.cacheStore = {};
}
/**
* Get all the data stored in the cache for a certain id.
*
* @param {any} id The ID to identify the entry.
* @return {any} The data from the cache. Undefined if not found.
*/
getEntry(id: any) : any {
if (!this.cacheStore[id]) {
this.cacheStore[id] = {};
}
return this.cacheStore[id];
}
/**
* Get the status of a module from the "cache".
*
* @param {any} id The ID to identify the entry.
* @param {string} name Name of the value to get.
* @param {boolean} [ignoreInvalidate] Whether it should always return the cached data, even if it's expired.
* @return {any} Cached value. Undefined if not cached or expired.
*/
getValue(id: any, name: string, ignoreInvalidate?: boolean) : any {
const entry = this.getEntry(id);
if (entry[name] && typeof entry[name].value != 'undefined') {
const now = Date.now();
// Invalidate after 5 minutes.
if (ignoreInvalidate || entry[name].timemodified + 300000 >= now) {
return entry[name].value;
}
}
return undefined;
}
/**
* Invalidate all the cached data for a certain entry.
*
* @param {any} id The ID to identify the entry.
*/
invalidate(id: any) : void {
const entry = this.getEntry(id);
for (let name in entry) {
entry[name].timemodified = 0;
}
}
/**
* Update the status of a module in the "cache".
*
* @param {any} id The ID to identify the entry.
* @param {string} name Name of the value to set.
* @param {any} value Value to set.
* @return {any} The set value.
*/
setValue(id: any, name: string, value: any) : any {
const entry = this.getEntry(id);
entry[name] = {
value: value,
timemodified: Date.now()
};
return value;
}
}

View File

@ -32,26 +32,110 @@ import { CoreConfigConstants } from '../configconstants';
import { Md5 } from 'ts-md5/dist/md5';
import { InAppBrowserObject } from '@ionic-native/in-app-browser';
/**
* PreSets accepted by the WS call.
*/
export interface CoreSiteWSPreSets {
getFromCache?: boolean; // Get the value from the cache if it's still valid.
saveToCache?: boolean; // Save the result to the cache.
omitExpires?: boolean; // Ignore cache expiration.
emergencyCache?: boolean; // Use the cache when a request fails. Defaults to true.
cacheKey?: string; // Extra key to add to the cache when storing this call, to identify the entry.
getCacheUsingCacheKey?: boolean; // Whether it should use cache key to retrieve the cached data instead of the request params.
getEmergencyCacheUsingCacheKey?: boolean; // Same as getCacheUsingCacheKey, but for emergency cache.
uniqueCacheKey?: boolean; // Whether it should only be 1 entry for this cache key (all entries with same key will be deleted).
filter?: boolean; // Whether to filter WS response (moodlewssettingfilter). Defaults to true.
rewriteurls?: boolean; // Whether to rewrite URLs (moodlewssettingfileurl). Defaults to true.
responseExpected?: boolean; // Defaults to true. Set to false when the expected response is null.
typeExpected?: string; // Defaults to 'object'. Use it when you expect a type that's not an object|array.
/**
* Get the value from the cache if it's still valid.
* @type {boolean}
*/
getFromCache?: boolean;
/**
* Save the result to the cache.
* @type {boolean}
*/
saveToCache?: boolean;
/**
* Ignore cache expiration.
* @type {boolean}
*/
omitExpires?: boolean;
/**
* Use the cache when a request fails. Defaults to true.
* @type {boolean}
*/
emergencyCache?: boolean;
/**
* Extra key to add to the cache when storing this call, to identify the entry.
* @type {string}
*/
cacheKey?: string;
/**
* Whether it should use cache key to retrieve the cached data instead of the request params.
* @type {boolean}
*/
getCacheUsingCacheKey?: boolean;
/**
* Same as getCacheUsingCacheKey, but for emergency cache.
* @type {boolean}
*/
getEmergencyCacheUsingCacheKey?: boolean;
/**
* Whether it should only be 1 entry for this cache key (all entries with same key will be deleted).
* @type {boolean}
*/
uniqueCacheKey?: boolean;
/**
* Whether to filter WS response (moodlewssettingfilter). Defaults to true.
* @type {boolean}
*/
filter?: boolean;
/**
* Whether to rewrite URLs (moodlewssettingfileurl). Defaults to true.
* @type {boolean}
*/
rewriteurls?: boolean;
/**
* Defaults to true. Set to false when the expected response is null.
* @type {boolean}
*/
responseExpected?: boolean;
/**
* Defaults to 'object'. Use it when you expect a type that's not an object|array.
* @type {string}
*/
typeExpected?: string;
};
/**
* Response of checking local_mobile status.
*/
export interface LocalMobileResponse {
code: number; // Code to identify the authentication method to use.
service?: string; // Name of the service to use.
warning?: string; // Code of the warning message.
coreSupported?: boolean; // Whether core SSO is supported.
/**
* Code to identify the authentication method to use.
* @type {number}
*/
code: number;
/**
* Name of the service to use.
* @type {string}
*/
service?: string;
/**
* Code of the warning message.
* @type {string}
*/
warning?: string;
/**
* Whether core SSO is supported.
* @type {boolean}
*/
coreSupported?: boolean;
}
/**
@ -435,7 +519,7 @@ export class CoreSite {
// Check if the method is available, use a prefixed version if possible.
// We ignore this check when we do not have the site info, as the list of functions is not loaded yet.
if (this.getInfo() && !this.wsAvailable(method, false)) {
const compatibilityMethod = CoreConstants.wsPrefix + method;
const compatibilityMethod = CoreConstants.WS_PREFIX + method;
if (this.wsAvailable(compatibilityMethod, false)) {
this.logger.info(`Using compatibility WS method '${compatibilityMethod}'`);
method = compatibilityMethod;
@ -482,14 +566,7 @@ export class CoreSite {
// We pass back a clone of the original object, this may
// prevent errors if in the callback the object is modified.
if (typeof response == 'object') {
if (Array.isArray(response)) {
return Array.from(response);
} else {
return Object.assign({}, response);
}
}
return response;
return this.utils.clone(response);
}).catch((error) => {
if (error.errorcode == 'invalidtoken' ||
(error.errorcode == 'accessexception' && error.message.indexOf('Invalid token - token expired') > -1)) {
@ -572,7 +649,7 @@ export class CoreSite {
// Let's try again with the compatibility prefix.
if (checkPrefix) {
return this.wsAvailable(CoreConstants.wsPrefix + method, false);
return this.wsAvailable(CoreConstants.WS_PREFIX + method, false);
}
return false;
@ -884,7 +961,7 @@ export class CoreSite {
return Promise.resolve({code: 0});
}
let observable = this.http.post(checkUrl, {service: service}).timeout(CoreConstants.wsTimeout);
let observable = this.http.post(checkUrl, {service: service}).timeout(CoreConstants.WS_TIMEOUT);
return this.utils.observableToPromise(observable).then((data: any) => {
if (typeof data != 'undefined' && data.errorcode === 'requirecorrectaccess') {
if (!retrying) {
@ -937,7 +1014,7 @@ export class CoreSite {
}
this.infos.functions.forEach((func) => {
if (func.name.indexOf(CoreConstants.wsPrefix) != -1) {
if (func.name.indexOf(CoreConstants.WS_PREFIX) != -1) {
appUsesLocalMobile = true;
}
});
@ -1081,7 +1158,7 @@ export class CoreSite {
};
if (!this.privateToken || !this.wsAvailable('tool_mobile_get_autologin_key') ||
(this.lastAutoLogin && this.timeUtils.timestamp() - this.lastAutoLogin < 6 * CoreConstants.secondsMinute)) {
(this.lastAutoLogin && this.timeUtils.timestamp() - this.lastAutoLogin < 6 * CoreConstants.SECONDS_MINUTE)) {
// No private token, WS not available or last auto-login was less than 6 minutes ago.
// Open the final URL without auto-login.
return Promise.resolve(open(url));

View File

@ -34,6 +34,8 @@ import { CoreCoursePickerMenuPopoverComponent } from './course-picker-menu/cours
import { CoreChronoComponent } from './chrono/chrono';
import { CoreLocalFileComponent } from './local-file/local-file';
import { CoreSitePickerComponent } from './site-picker/site-picker';
import { CoreTabsComponent } from './tabs/tabs';
import { CoreTabComponent } from './tabs/tab';
@NgModule({
declarations: [
@ -53,7 +55,9 @@ import { CoreSitePickerComponent } from './site-picker/site-picker';
CoreCoursePickerMenuPopoverComponent,
CoreChronoComponent,
CoreLocalFileComponent,
CoreSitePickerComponent
CoreSitePickerComponent,
CoreTabsComponent,
CoreTabComponent
],
entryComponents: [
CoreContextMenuPopoverComponent,
@ -80,7 +84,9 @@ import { CoreSitePickerComponent } from './site-picker/site-picker';
CoreContextMenuItemComponent,
CoreChronoComponent,
CoreLocalFileComponent,
CoreSitePickerComponent
CoreSitePickerComponent,
CoreTabsComponent,
CoreTabComponent
]
})
export class CoreComponentsModule {}

View File

@ -38,7 +38,7 @@ export class CoreContextMenuItemComponent implements OnInit, OnDestroy, OnChange
@Input() iconDescription?: string; // Name of the icon to be shown on the left side of the item.
@Input() iconAction?: string; // Name of the icon to be shown on the right side of the item. It represents the action to do on
// click. If is "spinner" an spinner will be shown. If no icon or spinner is selected, no action
// or link will work. If href but no iconAction is provided ion-arrow-right-c will be used.
// or link will work. If href but no iconAction is provided arrow-right will be used.
@Input() ariaDescription?: string; // Aria label to add to iconDescription.
@Input() ariaAction?: string; // Aria label to add to iconAction. If not set, it will be equal to content.
@Input() href?: string; // Link to go if no action provided.

View File

@ -15,6 +15,7 @@
import { Component } from '@angular/core';
import { NavParams, ViewController } from 'ionic-angular';
import { CoreContextMenuItemComponent } from './context-menu-item';
import { CoreLoggerProvider } from '../../providers/logger';
/**
* Component to display a list of items received by param in a popover.
@ -26,10 +27,12 @@ import { CoreContextMenuItemComponent } from './context-menu-item';
export class CoreContextMenuPopoverComponent {
title: string;
items: CoreContextMenuItemComponent[];
protected logger: any;
constructor(navParams: NavParams, private viewCtrl: ViewController) {
constructor(navParams: NavParams, private viewCtrl: ViewController, logger: CoreLoggerProvider) {
this.title = navParams.get('title');
this.items = navParams.get('items') || [];
this.logger = logger.getInstance('CoreContextMenuPopoverComponent');
}
/**
@ -51,7 +54,10 @@ export class CoreContextMenuPopoverComponent {
event.preventDefault();
event.stopPropagation();
if (!item.iconAction || item.iconAction == 'spinner') {
if (!item.iconAction) {
this.logger.warn('Items with action must have an icon action to work', item);
return false;
} else if (item.iconAction == 'spinner') {
return false;
}

View File

@ -27,6 +27,7 @@ core-empty-box {
left: initial;
right: initial;
z-index: initial;
height: auto;
}
.icon {

View File

@ -102,10 +102,10 @@ export class CoreFileComponent implements OnInit, OnDestroy {
return this.filepoolProvider.getFileStateByUrl(this.siteId, this.fileUrl, this.timemodified).then((state) => {
let canDownload = this.sitesProvider.getCurrentSite().canDownloadFiles();
this.isDownloaded = state === CoreConstants.downloaded || state === CoreConstants.outdated;
this.isDownloading = canDownload && state === CoreConstants.downloading;
this.showDownload = canDownload && (state === CoreConstants.notDownloaded || state === CoreConstants.outdated ||
(this.alwaysDownload && state === CoreConstants.downloaded));
this.isDownloaded = state === CoreConstants.DOWNLOADED || state === CoreConstants.OUTDATED;
this.isDownloading = canDownload && state === CoreConstants.DOWNLOADING;
this.showDownload = canDownload && (state === CoreConstants.NOT_DOWNLOADED || state === CoreConstants.OUTDATED ||
(this.alwaysDownload && state === CoreConstants.DOWNLOADED));
});
}
@ -207,7 +207,7 @@ export class CoreFileComponent implements OnInit, OnDestroy {
let subPromise;
if (status === CoreConstants.notDownloaded) {
if (status === CoreConstants.NOT_DOWNLOADED) {
// File is not downloaded, download and then return the local URL.
subPromise = this.downloadFile();
} else {

View File

@ -0,0 +1,64 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, Output, OnInit, OnDestroy, ElementRef, EventEmitter } from '@angular/core';
import { CoreTabsComponent } from './tabs';
/**
* A tab to use inside core-tabs. The content of this tab will be displayed when the tab is selected.
*
* You must provide either a title or an icon for the tab.
*
* Example usage:
*
* <core-tabs selectedIndex="1">
* <core-tab [title]="'core.courses.timeline' | translate" (ionSelect)="switchTab('timeline')">
* <!-- Tab contents. -->
* </core-tab>
* </core-tabs>
*/
@Component({
selector: 'core-tab',
template: '<ng-content></ng-content>'
})
export class CoreTabComponent implements OnInit, OnDestroy {
@Input() title?: string; // The tab title.
@Input() icon?: string; // The tab icon.
@Input() badge?: string; // A badge to add in the tab.
@Input() badgeStyle?: string; // The badge color.
@Input() enabled?: boolean = true; // Whether the tab is enabled.
@Input() show?: boolean = true; // Whether the tab should be shown.
@Input() id?: string; // An ID to identify the tab.
@Output() ionSelect: EventEmitter<CoreTabComponent> = new EventEmitter<CoreTabComponent>();
element: HTMLElement; // The core-tab element.
constructor(private tabs: CoreTabsComponent, element: ElementRef) {
this.element = element.nativeElement;
}
/**
* Component being initialized.
*/
ngOnInit() {
this.tabs.addTab(this);
}
/**
* Component destroyed.
*/
ngOnDestroy() {
this.tabs.removeTab(this);
}
}

View File

@ -0,0 +1,12 @@
<div class="core-tabs-bar">
<ng-container *ngFor="let tab of tabs; let idx = index">
<a *ngIf="tab.show" [attr.aria-selected]="selected == idx" (click)="selectTab(idx)">
<ion-icon *ngIf="tab.icon" [name]="tab.icon"></ion-icon>
<span *ngIf="tab.title">{{ tab.title }}</span>
<ion-badge *ngIf="tab.badge" [color]="tab.badgeStyle" class="tab-badge">{{tab.badge}}</ion-badge>
</a>
</ng-container>
</div>
<div #originalTabs>
<ng-content></ng-content>
</div>

View File

@ -0,0 +1,11 @@
core-tabs {
.core-tabs-bar {
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
> a {
font-size: 1.6rem;
}
}
}

View File

@ -0,0 +1,32 @@
core-tabs {
.core-tabs-bar {
@include position(null, null, 0, 0);
z-index: $z-index-toolbar;
display: flex;
width: 100%;
background: $core-top-tabs-background;
> a {
@extend .tab-button;
background: $core-top-tabs-background;
color: $core-top-tabs-color !important;
border-bottom: 1px solid $core-top-tabs-border;
font-size: 1.6rem;
&[aria-selected=true] {
color: $core-top-tabs-color-active !important;
border-bottom: 2px solid $core-top-tabs-color-active;
}
}
}
core-tab {
display: none;
&.selected {
display: block;
}
}
}

View File

@ -0,0 +1,183 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, Output, EventEmitter, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
import { CoreTabComponent } from './tab';
/**
* This component displays some tabs that usually share data between them.
*
* If your tabs don't share any data then you should probably use ion-tabs. This component doesn't use different ion-nav
* for each tab, so it will not load pages.
*
* Example usage:
*
* <core-tabs selectedIndex="1">
* <core-tab [title]="'core.courses.timeline' | translate" (ionSelect)="switchTab('timeline')">
* <!-- Tab contents. -->
* </core-tab>
* </core-tabs>
*
* Obviously, the tab contents will only be shown if that tab is selected.
*/
@Component({
selector: 'core-tabs',
templateUrl: 'tabs.html'
})
export class CoreTabsComponent implements OnInit, AfterViewInit {
@Input() selectedIndex?: number = 0; // Index of the tab to select.
@Output() ionChange: EventEmitter<CoreTabComponent> = new EventEmitter<CoreTabComponent>(); // Emitted when the tab changes.
@ViewChild('originalTabs') originalTabsRef: ElementRef;
tabs: CoreTabComponent[] = []; // List of tabs.
selected: number; // Selected tab number.
protected originalTabsContainer: HTMLElement; // The container of the original tabs. It will include each tab's content.
constructor() {}
/**
* Component being initialized.
*/
ngOnInit() {
this.originalTabsContainer = this.originalTabsRef.nativeElement;
}
/**
* View has been initialized.
*/
ngAfterViewInit() {
let selectedIndex = this.selectedIndex || 0,
selectedTab = this.tabs[selectedIndex];
if (!selectedTab.enabled || !selectedTab.show) {
// The tab is not enabled or not shown. Get the first tab that is enabled.
selectedTab = this.tabs.find((tab, index) => {
if (tab.enabled && tab.show) {
selectedIndex = index;
return true;
}
return false;
});
}
if (selectedTab) {
this.selectTab(selectedIndex);
}
}
/**
* Add a new tab if it isn't already in the list of tabs.
*
* @param {CoreTabComponent} tab The tab to add.
*/
addTab(tab: CoreTabComponent) : void {
// Check if tab is already in the list.
if (this.getIndex(tab) == -1) {
this.tabs.push(tab);
this.sortTabs();
}
}
/**
* Get the index of tab.
*
* @param {any} tab [description]
* @return {number} [description]
*/
getIndex(tab: any) : number {
for (let i = 0; i < this.tabs.length; i++) {
let t = this.tabs[i];
if (t === tab || (typeof t.id != 'undefined' && t.id === tab.id)) {
return i;
}
}
return -1;
}
/**
* Get the current selected tab.
*
* @return {CoreTabComponent} Selected tab.
*/
getSelected() : CoreTabComponent {
return this.tabs[this.selected];
}
/**
* Remove a tab from the list of tabs.
*
* @param {CoreTabComponent} tab The tab to remove.
*/
removeTab(tab: CoreTabComponent) : void {
const index = this.getIndex(tab);
this.tabs.splice(index, 1);
}
/**
* Select a certain tab.
*
* @param {number} index The index of the tab to select.
*/
selectTab(index: number) : void {
if (index == this.selected) {
// Already selected.
return;
}
if (index < 0 || index >= this.tabs.length) {
// Index isn't valid, select the first one.
index = 0;
}
const currenTab = this.getSelected(),
newTab = this.tabs[index];
if (!newTab.enabled || !newTab.show) {
// The tab isn't enabled or shown, stop.
return;
}
if (currenTab) {
// Unselect previous selected tab.
currenTab.element.classList.remove('selected');
}
this.selected = index;
newTab.element.classList.add('selected');
newTab.ionSelect.emit(newTab);
this.ionChange.emit(newTab);
}
/**
* Sort the tabs, keeping the same order as in the original list.
*/
protected sortTabs() {
if (this.originalTabsContainer) {
let newTabs = [],
newSelected;
this.tabs.forEach((tab, index) => {
let originalIndex = Array.prototype.indexOf.call(this.originalTabsContainer.children, tab.element);
if (originalIndex != -1) {
newTabs[originalIndex] = tab;
if (this.selected == index) {
newSelected = originalIndex;
}
}
});
this.tabs = newTabs;
}
}
}

View File

@ -16,33 +16,34 @@
* Static class to contain all the core constants.
*/
export class CoreConstants {
public static secondsYear = 31536000;
public static secondsDay = 86400;
public static secondsHour = 3600;
public static secondsMinute = 60;
public static wifiDownloadThreshold = 104857600; // 100MB.
public static downloadThreshold = 10485760; // 10MB.
public static dontShowError = 'CoreDontShowError';
public static noSiteId = 'NoSite';
public static SECONDS_YEAR = 31536000;
public static SECONDS_WEEK = 604800;
public static SECONDS_DAY = 86400;
public static SECONDS_HOUR = 3600;
public static SECONDS_MINUTE = 60;
public static WIFI_DOWNLOAD_THRESHOLD = 104857600; // 100MB.
public static DOWNLOAD_THRESHOLD = 10485760; // 10MB.
public static DONT_SHOW_ERROR = 'CoreDontShowError';
public static NO_SITE_ID = 'NoSite';
// Settings constants.
public static settingsRichTextEditor = 'CoreSettingsRichTextEditor';
public static settingsNotificationSound = 'CoreSettingsNotificationSound';
public static settingsSyncOnlyOnWifi = 'mmCoreSyncOnlyOnWifi';
public static SETTINGS_RICH_TEXT_EDITOR = 'CoreSettingsRichTextEditor';
public static SETTINGS_NOTIFICATION_SOUND = 'CoreSettingsNotificationSound';
public static SETTINGS_SYNC_ONLY_ON_WIFI = 'CoreSettingsSyncOnlyOnWifi';
// WS constants.
public static wsTimeout = 30000;
public static wsPrefix = 'local_mobile_';
public static WS_TIMEOUT = 30000;
public static WS_PREFIX = 'local_mobile_';
// Login constants.
public static loginSSOCode = 2; // SSO in browser window is required.
public static loginSSOInAppCode = 3; // SSO in embedded browser is required.
public static loginLaunchData = 'mmLoginLaunchData';
public static LOGIN_SSO_CODE = 2; // SSO in browser window is required.
public static LOGIN_SSO_INAPP_CODE = 3; // SSO in embedded browser is required.
public static LOGIN_LAUNCH_DATA = 'CoreLoginLaunchData';
// Download status constants.
public static downloaded = 'downloaded';
public static downloading = 'downloading';
public static notDownloaded = 'notdownloaded';
public static outdated = 'outdated';
public static notDownloadable = 'notdownloadable';
public static DOWNLOADED = 'downloaded';
public static DOWNLOADING = 'downloading';
public static NOT_DOWNLOADED = 'notdownloaded';
public static OUTDATED = 'outdated';
public static NOT_DOWNLOADABLE = 'notdownloadable';
}

View File

@ -0,0 +1,514 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injector } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CoreAppProvider } from '../../../providers/app';
import { CoreFilepoolProvider } from '../../../providers/filepool';
import { CoreSitesProvider } from '../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../providers/utils/dom';
import { CoreUtilsProvider } from '../../../providers/utils/utils';
import { CoreCourseProvider } from '../providers/course';
import { CoreCourseModulePrefetchHandler } from '../providers/module-prefetch-delegate';
import { CoreConstants } from '../../constants';
/**
* A prefetch function to be passed to prefetchPackage.
* This function should NOT call storePackageStatus, downloadPackage or prefetchPakage from filepool.
* It receives the same params as prefetchPackage except the function itself. This includes all extra parameters sent after siteId.
* The string returned by this function will be stored as "extra" data in the filepool package. If you don't need to store
* extra data, don't return anything.
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @param {boolean} single True if we're downloading a single module, false if we're downloading a whole section.
* @param {string} siteId Site ID. If not defined, current site.
* @return {Promise<string>} Promise resolved when the prefetch finishes. The string returned will be stored as "extra" data in the
* filepool package. If you don't need to store extra data, don't return anything.
*/
export type prefetchFunction = (module: any, courseId: number, single: boolean, siteId: string, ...args) => Promise<string>;
/**
* Base prefetch handler to be registered in CoreCourseModulePrefetchDelegate. It is useful to minimize the amount of
* functions that handlers need to implement. It also provides some helper features like preventing a module to be
* downloaded twice at the same time.
*
* If your handler inherits from this service, you just need to override the functions that you want to change.
*
* The implementation of this default handler is aimed for resources that only need to prefetch files, not WebService calls.
*
* By default, prefetching a module will only download its files (downloadOrPrefetch). This might be enough for resources.
* If you need to prefetch WebServices, then you need to override the "download" and "prefetch" functions. In this case, it's
* recommended to call the prefetchPackage function since it'll handle changing the status of the module.
*/
export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePrefetchHandler {
/**
* A name to identify the addon.
* @type {string}
*/
name = 'CoreCourseModulePrefetchHandlerBase';
/**
* Name of the module. It should match the "modname" of the module returned in core_course_get_contents.
* @type {string}
*/
modname = '';
/**
* The handler's component.
* @type {string}
*/
component = 'core_module';
/**
* The RegExp to check updates. If a module has an update whose name matches this RegExp, the module will be marked
* as outdated. This RegExp is ignored if hasUpdates function is defined.
* @type {RegExp}
*/
updatesNames = /^.*files$/;
/**
* Whether the module is a resource (true) or an activity (false).
* @type {boolean}
*/
isResource: boolean;
/**
* List of download promises to prevent downloading the module twice at the same time.
* @type {{[s: string]: {[s: string]: Promise<any>}}}
*/
protected downloadPromises: {[s: string]: {[s: string]: Promise<any>}} = {};
// List of services that will be injected using injector. It's done like this so subclasses don't have to send all the
// services to the parent in the constructor.
protected translate: TranslateService;
protected appProvider: CoreAppProvider;
protected courseProvider: CoreCourseProvider;
protected filepoolProvider: CoreFilepoolProvider;
protected sitesProvider: CoreSitesProvider;
protected domUtils: CoreDomUtilsProvider;
protected utils: CoreUtilsProvider;
constructor(injector: Injector) {
this.translate = injector.get(TranslateService);
this.appProvider = injector.get(CoreAppProvider);
this.courseProvider = injector.get(CoreCourseProvider);
this.filepoolProvider = injector.get(CoreFilepoolProvider);
this.sitesProvider = injector.get(CoreSitesProvider);
this.domUtils = injector.get(CoreDomUtilsProvider);
this.utils = injector.get(CoreUtilsProvider);
}
/**
* Add an ongoing download to the downloadPromises list. When the promise finishes it will be removed.
*
* @param {number} id Unique identifier per component.
* @param {Promise<any>} promise Promise to add.
* @param {String} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise of the current download.
*/
addOngoingDownload(id: number, promise: Promise<any>, siteId?: string) : Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
const uniqueId = this.getUniqueId(id);
if (!this.downloadPromises[siteId]) {
this.downloadPromises[siteId] = {};
}
this.downloadPromises[siteId][uniqueId] = promise.finally(() => {
delete this.downloadPromises[siteId][uniqueId];
});
return this.downloadPromises[siteId][uniqueId];
}
/**
* Download the module.
*
* @param {any} module The module object returned by WS.
* @param {number} courseId Course ID.
* @return {Promise<any>} Promise resolved when all content is downloaded.
*/
download(module: any, courseId: number) : Promise<any> {
return this.downloadOrPrefetch(module, courseId, false);
}
/**
* Download or prefetch the content.
*
* @param {any} module The module object returned by WS.
* @param {number} courseId Course ID.
* @param {boolean} [prefetch] True to prefetch, false to download right away.
* @param {string} [dirPath] Path of the directory where to store all the content files. This is to keep the files
* relative paths and make the package work in an iframe. Undefined to download the files
* in the filepool root folder.
* @return {Promise<any>} Promise resolved when all content is downloaded. Data returned is not reliable.
*/
downloadOrPrefetch(module: any, courseId: number, prefetch?: boolean, dirPath?: string) : Promise<any> {
if (!this.appProvider.isOnline()) {
// Cannot download in offline.
return Promise.reject(this.translate.instant('core.networkerrormsg'));
}
const siteId = this.sitesProvider.getCurrentSiteId();
// Load module contents (ignore cache so we always have the latest data).
return this.loadContents(module, courseId, true).then(() => {
// Get the intro files.
return this.getIntroFiles(module, courseId);
}).then((introFiles) => {
let downloadFn = prefetch ? this.filepoolProvider.prefetchPackage.bind(this.filepoolProvider) :
this.filepoolProvider.downloadPackage.bind(this.filepoolProvider),
contentFiles = this.getContentDownloadableFiles(module),
promises = [];
if (dirPath) {
// Download intro files in filepool root folder.
promises.push(this.filepoolProvider.downloadOrPrefetchFiles(siteId, introFiles, prefetch, false,
this.component, module.id));
// Download content files inside dirPath.
promises.push(downloadFn(siteId, contentFiles, this.component, module.id, undefined, dirPath));
} else {
// No dirPath, download everything in filepool root folder.
let files = introFiles.concat(contentFiles);
promises.push(downloadFn(siteId, files, this.component, module.id));
}
return Promise.all(promises);
});
}
/**
* Returns a list of content files that can be downloaded.
*
* @param {any} module The module object returned by WS.
* @return {any[]} List of files.
*/
getContentDownloadableFiles(module: any) {
let files = [];
if (module.contents && module.contents.length) {
module.contents.forEach((content) => {
if (this.isFileDownloadable(content)) {
files.push(content);
}
});
}
return files;
}
/**
* Get the download size of a module.
*
* @param {any} module Module.
* @param {Number} courseId Course ID the module belongs to.
* @param {boolean} [single] True if we're downloading a single module, false if we're downloading a whole section.
* @return {Promise<{size: number, total: boolean}>} Promise resolved with the size and a boolean indicating if it was able
* to calculate the total size.
*/
getDownloadSize(module: any, courseId: number, single?: boolean) : Promise<{size: number, total: boolean}> {
return this.getFiles(module, courseId).then((files) => {
return this.utils.sumFileSizes(files);
}).catch(() => {
return {size: -1, total: false};
});
}
/**
* Get the downloaded size of a module. If not defined, we'll use getFiles to calculate it (it can be slow).
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @return {number|Promise<number>} Size, or promise resolved with the size.
*/
getDownloadedSize?(module: any, courseId: number) : number|Promise<number> {
const siteId = this.sitesProvider.getCurrentSiteId();
return this.filepoolProvider.getFilesSizeByComponent(siteId, this.component, module.id);
}
/**
* Get list of files. If not defined, we'll assume they're in module.contents.
*
* @param {any} module Module.
* @param {Number} courseId Course ID the module belongs to.
* @param {boolean} [single] True if we're downloading a single module, false if we're downloading a whole section.
* @return {Promise<any[]>} Promise resolved with the list of files.
*/
getFiles(module: any, courseId: number, single?: boolean) : Promise<any[]> {
// Load module contents if needed.
return this.loadContents(module, courseId).then(() => {
return this.getIntroFiles(module, courseId).then((files) => {
return files.concat(this.getContentDownloadableFiles(module));
});
});
}
/**
* Returns module intro files.
*
* @param {any} module The module object returned by WS.
* @param {number} courseId Course ID.
* @return {Promise<any[]>} Promise resolved with list of intro files.
*/
getIntroFiles(module: any, courseId: number) : Promise<any[]> {
return Promise.resolve(this.getIntroFilesFromInstance(module));
}
/**
* Returns module intro files from instance.
*
* @param {any} module The module object returned by WS.
* @param {any} [instance] The instance to get the intro files (book, assign, ...). If not defined, module will be used.
* @return {any[]} List of intro files.
*/
getIntroFilesFromInstance(module: any, instance?: any) {
if (instance) {
if (typeof instance.introfiles != 'undefined') {
return instance.introfiles;
} else if (instance.intro) {
return this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(instance.intro);
}
}
if (module.description) {
return this.domUtils.extractDownloadableFilesFromHtmlAsFakeFileObjects(module.description);
}
return [];
}
/**
* If there's an ongoing download for a certain identifier return it.
*
* @param {number} id Unique identifier per component.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise of the current download.
*/
getOngoingDownload(id: number, siteId?: string) : Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
if (this.isDownloading(id, siteId)) {
// There's already a download ongoing, return the promise.
return this.downloadPromises[siteId][this.getUniqueId(id)];
}
return Promise.resolve();
}
/**
* Create unique identifier using component and id.
*
* @param {number} id Unique ID inside component.
* @return {string} Unique ID.
*/
getUniqueId(id: number) {
return this.component + '#' + id;
}
/**
* Invalidate the prefetched content.
*
* @param {number} moduleId The module ID.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateContent(moduleId: number) : Promise<any> {
const promises = [],
siteId = this.sitesProvider.getCurrentSiteId();
promises.push(this.courseProvider.invalidateModule(moduleId));
promises.push(this.filepoolProvider.invalidateFilesByComponent(siteId, this.component, moduleId));
return Promise.all(promises);
}
/**
* Invalidate WS calls needed to determine module status. It doesn't need to invalidate check updates.
* It should NOT invalidate files nor all the prefetched data.
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @return {Promise<any>} Promise resolved when invalidated.
*/
invalidateModule(module: any, courseId: number) : Promise<any> {
return this.courseProvider.invalidateModule(module.id);
}
/**
* Check if a module can be downloaded. If the function is not defined, we assume that all modules are downloadable.
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @return {boolean|Promise<boolean>} Whether the module can be downloaded. The promise should never be rejected.
*/
isDownloadable(module: any, courseId: number) : boolean|Promise<boolean> {
// By default, mark all instances as downloadable.
return true;
}
/**
* Check if a there's an ongoing download for the given identifier.
*
* @param {number} id Unique identifier per component.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Boolean} True if downloading, false otherwise.
*/
isDownloading(id: number, siteId?: string) : boolean {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
return !!(this.downloadPromises[siteId] && this.downloadPromises[siteId][this.getUniqueId(id)]);
}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} A boolean, or a promise resolved with a boolean, indicating if the handler is enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Check if a file is downloadable.
*
* @param {any} file File to check.
* @return {boolean} Whether the file is downloadable.
*/
isFileDownloadable(file: any) : boolean {
return file.type === 'file';
}
/**
* Load module contents into module.contents if they aren't loaded already.
*
* @param {any} module Module to load the contents.
* @param {number} [courseId] The course ID. Recommended to speed up the process and minimize data usage.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise} Promise resolved when loaded.
*/
loadContents(module: any, courseId: number, ignoreCache?: boolean) : Promise<void> {
if (this.isResource) {
return this.courseProvider.loadModuleContents(module, courseId, undefined, false, ignoreCache);
}
return Promise.resolve();
}
/**
* Prefetch a module.
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @param {boolean} [single] True if we're downloading a single module, false if we're downloading a whole section.
* @return {Promise<any>} Promise resolved when done.
*/
prefetch(module: any, courseId?: number, single?: boolean): Promise<any> {
return this.downloadOrPrefetch(module, courseId, true);
}
/**
* Prefetch the module, setting package status at start and finish.
*
* Example usage from a child instance:
* return this.prefetchPackage(module, courseId, single, this.prefetchModule.bind(this), siteId, someParam, anotherParam);
*
* Then the function "prefetchModule" will receive params:
* prefetchModule(module, courseId, single, siteId, someParam, anotherParam)
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @param {boolean} [single] True if we're downloading a single module, false if we're downloading a whole section.
* @param {prefetchFunction} downloadFn Function to perform the prefetch. Please check the documentation of prefetchFunction.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the module has been downloaded. Data returned is not reliable.
*/
prefetchPackage(module: any, courseId: number, single: boolean, downloadFn: prefetchFunction, siteId?: string, ...args) :
Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
if (!this.appProvider.isOnline()) {
// Cannot prefetch in offline.
return Promise.reject(this.translate.instant('core.networkerrormsg'));
}
if (this.isDownloading(module.id, siteId)) {
// There's already a download ongoing for this module, return the promise.
return this.getOngoingDownload(module.id, siteId);
}
const prefetchPromise = this.setDownloading(module.id, siteId).then(() => {
// Package marked as downloading, call the download function.
// Send all the params except downloadFn. This includes all params passed after siteId.
return downloadFn.apply(downloadFn, [module, courseId, single, siteId].concat(args));
}).then((extra: string) => {
// Prefetch finished, mark as downloaded.
return this.setDownloaded(module.id, siteId, extra);
}).catch((error) => {
// Error prefetching, go back to previous status and reject the promise.
return this.setPreviousStatusAndReject(module.id, error, siteId);
});
return this.addOngoingDownload(module.id, prefetchPromise, siteId);
}
/**
* Mark the module as downloaded.
*
* @param {number} id Unique identifier per component.
* @param {string} [siteId] Site ID. If not defined, current site.
* @param {string} [extra] Extra data to store.
* @return {Promise<any>} Promise resolved when done.
*/
setDownloaded(id: number, siteId?: string, extra?: string) : Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
return this.filepoolProvider.storePackageStatus(siteId, CoreConstants.DOWNLOADED, this.component, id, extra);
}
/**
* Mark the module as downloading.
*
* @param {number} id Unique identifier per component.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when done.
*/
setDownloading(id: number, siteId?: string) : Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
return this.filepoolProvider.storePackageStatus(siteId, CoreConstants.DOWNLOADING, this.component, id);
}
/**
* Set previous status and return a rejected promise.
*
* @param {number} id Unique identifier per component.
* @param {any} [error] Error to return.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<never>} Rejected promise.
*/
setPreviousStatusAndReject(id: number, error?: any, siteId?: string) : Promise<never> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
return this.filepoolProvider.setPackagePreviousStatus(siteId, this.component, id).then(() => {
return Promise.reject(error);
});
}
/**
* Remove module downloaded files. If not defined, we'll use getFiles to remove them (slow).
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @return {Promise<any>} Promise resolved when done.
*/
removeFiles(module: any, courseId: number) : Promise<any> {
return this.filepoolProvider.removeFilesByComponent(this.sitesProvider.getCurrentSiteId(), this.component, module.id);
}
}

View File

@ -0,0 +1,55 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreComponentsModule } from '../../../components/components.module';
import { CoreDirectivesModule } from '../../../directives/directives.module';
import { CoreCourseFormatComponent } from './format/format';
import { CoreCourseModuleComponent } from './module/module';
import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion';
import { CoreCourseModuleDescriptionComponent } from './module-description/module-description';
import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsupported-module';
@NgModule({
declarations: [
CoreCourseFormatComponent,
CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent,
CoreCourseModuleDescriptionComponent,
CoreCourseUnsupportedModuleComponent
],
imports: [
CommonModule,
IonicModule,
TranslateModule.forChild(),
CoreComponentsModule,
CoreDirectivesModule
],
providers: [
],
exports: [
CoreCourseFormatComponent,
CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent,
CoreCourseModuleDescriptionComponent,
CoreCourseUnsupportedModuleComponent
],
entryComponents: [
CoreCourseUnsupportedModuleComponent
]
})
export class CoreCourseComponentsModule {}

View File

@ -0,0 +1,83 @@
<!-- Default course format. -->
<div *ngIf="!componentInstances.courseFormat">
<!-- Course summary. By default we only display the course progress. -->
<ion-list no-lines *ngIf="!componentInstances.courseSummary">
<ion-item *ngIf="course.progress != null && course.progress >= 0">
<core-progress-bar [progress]="course.progress"></core-progress-bar>
</ion-item>
</ion-list>
<ng-template #courseSummary></ng-template>
<core-loading [hideUntil]="loaded">
<!-- Section selector. -->
<div *ngIf="!componentInstances.sectionSelector && displaySectionSelector && sections && sections.length" no-padding class="clearfix">
<!-- @todo: How to display availabilityinfo and not visible messages? -->
<ion-select [ngModel]="selectedSection" (ngModelChange)="sectionChanged($event)" [compareWith]="compareSections" [selectOptions]="selectOptions" float-start>
<ion-option *ngFor="let section of sections" [value]="section">{{section.formattedName || section.name}}</ion-option>
</ion-select>
<!-- Section download. -->
<ng-container *ngTemplateOutlet="sectionDownloadTemplate; context: {section: selectedSection}"></ng-container>
</div>
<ng-template #sectionSelector></ng-template>
<!-- Single section. -->
<div *ngIf="selectedSection && selectedSection.id != allSectionsId">
<ng-container *ngIf="!componentInstances.singleSection">
<ng-container *ngTemplateOutlet="sectionTemplate; context: {section: selectedSection}"></ng-container>
<core-empty-box *ngIf="!selectedSection.hasContent" icon="qr-scanner" [message]="'core.course.nocontentavailable' | translate"></core-empty-box>
</ng-container>
<ng-template #singleSection></ng-template>
</div>
<!-- Multiple sections. -->
<div *ngIf="selectedSection && selectedSection.id == allSectionsId">
<ng-container *ngIf="!componentInstances.allSections">
<ng-container *ngFor="let section of sections">
<ng-container *ngTemplateOutlet="sectionTemplate; context: {section: section}"></ng-container>
</ng-container>
</ng-container>
<ng-template #allSections></ng-template>
</div>
</core-loading>
</div>
<!-- Template to render a section. -->
<ng-template #sectionTemplate let-section="section">
<section ion-list *ngIf="section.hasContent">
<!-- Title is only displayed when viewing all sections. -->
<ion-item-divider text-wrap color="light" *ngIf="selectedSection.id == allSectionsId && section.name">
<core-format-text [text]="section.name"></core-format-text>
<!-- Section download. -->
<ng-container *ngTemplateOutlet="sectionDownloadTemplate; context: {section: section}"></ng-container>
</ion-item-divider>
<ion-item text-wrap *ngIf="section.summary">
<core-format-text [text]="section.summary"></core-format-text>
</ion-item>
<ng-container *ngFor="let module of section.modules">
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [courseId]="course.id" (completionChanged)="completionChanged.emit()"></core-course-module>
</ng-container>
</section>
</ng-template>
<!-- Template to render a section download button/progress. -->
<ng-template #sectionDownloadTemplate let-section="section">
<div *ngIf="section && downloadEnabled" float-end>
<!-- Download button. -->
<button *ngIf="section.showDownload && !section.isDownloading && !section.isCalculating" (click)="prefetch($event, section)" ion-button icon-only clear color="dark" [attr.aria-label]="'core.download' | translate">
<ion-icon name="cloud-download"></ion-icon>
</button>
<!-- Refresh button. -->
<button *ngIf="section.showRefresh && !section.isDownloading && !section.isCalculating" (click)="prefetch($event, section)" ion-button icon-only clear color="dark" [attr.aria-label]="'core.refresh' | translate">
<ion-icon name="refresh"></ion-icon>
</button>
<!-- Spinner (downloading or calculating status). -->
<ion-spinner *ngIf="(section.isDownloading && section.total > 0) || section.isCalculating"></ion-spinner>
<!-- Download progress. -->
<ion-badge class="core-course-download-section-progress" *ngIf="section.isDownloading && section.total > 0 && section.count < section.total">{{section.count}} / {{section.total}}</ion-badge>
</div>
</ng-template>
<!-- Custom course format that overrides the default one. -->
<ng-template #courseFormat></ng-template>

View File

@ -0,0 +1,319 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, OnInit, OnChanges, OnDestroy, ViewContainerRef, ComponentFactoryResolver, ViewChild, ChangeDetectorRef,
SimpleChange, Output, EventEmitter } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CoreEventsProvider } from '../../../../providers/events';
import { CoreLoggerProvider } from '../../../../providers/logger';
import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreCourseProvider } from '../../../course/providers/course';
import { CoreCourseHelperProvider } from '../../../course/providers/helper';
import { CoreCourseFormatDelegate } from '../../../course/providers/format-delegate';
import { CoreCourseModulePrefetchDelegate } from '../../../course/providers/module-prefetch-delegate';
/**
* Component to display course contents using a certain format. If the format isn't found, use default one.
*
* The inputs of this component will be shared with the course format components. Please use CoreCourseFormatDelegate
* to register your handler for course formats.
*
* Example usage:
*
* <core-course-format [course]="course" [sections]="sections" (completionChanged)="onCompletionChange()"></core-course-format>
*/
@Component({
selector: 'core-course-format',
templateUrl: 'format.html'
})
export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
@Input() course: any; // The course to render.
@Input() sections: any[]; // List of course sections.
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
@Output() completionChanged?: EventEmitter<void>; // Will emit an event when any module completion changes.
// Get the containers where to inject dynamic components. We use a setter because they might be inside a *ngIf.
@ViewChild('courseFormat', { read: ViewContainerRef }) set courseFormat(el: ViewContainerRef) {
if (this.course) {
this.createComponent('courseFormat', this.cfDelegate.getCourseFormatComponent(this.course), el);
} else {
// The component hasn't been initialized yet. Store the container.
this.componentContainers['courseFormat'] = el;
}
};
@ViewChild('courseSummary', { read: ViewContainerRef }) set courseSummary(el: ViewContainerRef) {
this.createComponent('courseSummary', this.cfDelegate.getCourseSummaryComponent(this.course), el);
};
@ViewChild('sectionSelector', { read: ViewContainerRef }) set sectionSelector(el: ViewContainerRef) {
this.createComponent('sectionSelector', this.cfDelegate.getSectionSelectorComponent(this.course), el);
};
@ViewChild('singleSection', { read: ViewContainerRef }) set singleSection(el: ViewContainerRef) {
this.createComponent('singleSection', this.cfDelegate.getSingleSectionComponent(this.course), el);
};
@ViewChild('allSections', { read: ViewContainerRef }) set allSections(el: ViewContainerRef) {
this.createComponent('allSections', this.cfDelegate.getAllSectionsComponent(this.course), el);
};
// Instances and containers of all the components that the handler could define.
protected componentContainers: {[type: string]: ViewContainerRef} = {};
componentInstances: {[type: string]: any} = {};
displaySectionSelector: boolean;
selectedSection: any;
allSectionsId: number = CoreCourseProvider.ALL_SECTIONS_ID;
selectOptions: any = {};
loaded: boolean;
protected logger;
protected sectionStatusObserver;
constructor(logger: CoreLoggerProvider, private cfDelegate: CoreCourseFormatDelegate, translate: TranslateService,
private factoryResolver: ComponentFactoryResolver, private cdr: ChangeDetectorRef,
private courseHelper: CoreCourseHelperProvider, private domUtils: CoreDomUtilsProvider,
eventsProvider: CoreEventsProvider, private sitesProvider: CoreSitesProvider,
prefetchDelegate: CoreCourseModulePrefetchDelegate) {
this.logger = logger.getInstance('CoreCourseFormatComponent');
this.selectOptions.title = translate.instant('core.course.sections');
this.completionChanged = new EventEmitter();
// Listen for section status changes.
this.sectionStatusObserver = eventsProvider.on(CoreEventsProvider.SECTION_STATUS_CHANGED, (data) => {
if (this.downloadEnabled && this.sections && this.sections.length && this.course && data.sectionId &&
data.courseId == this.course.id) {
// Check if the affected section is being downloaded. If so, we don't update section status
// because it'll already be updated when the download finishes.
let downloadId = this.courseHelper.getSectionDownloadId({id: data.sectionId});
if (prefetchDelegate.isBeingDownloaded(downloadId)) {
return;
}
// Get the affected section.
let section;
for (let i = 0; i < this.sections.length; i++) {
let s = this.sections[i];
if (s.id === data.sectionId) {
section = s;
break;
}
}
if (!section) {
// Section not found, stop.
return;
}
// Recalculate the status.
this.courseHelper.calculateSectionStatus(section, this.course.id, false).then(() => {
if (section.isDownloading && !prefetchDelegate.isBeingDownloaded(downloadId)) {
// All the modules are now downloading, set a download all promise.
this.prefetch(section, false);
}
});
}
}, this.sitesProvider.getCurrentSiteId());
}
/**
* Component being initialized.
*/
ngOnInit() {
this.displaySectionSelector = this.cfDelegate.displaySectionSelector(this.course);
this.createComponent(
'courseFormat', this.cfDelegate.getCourseFormatComponent(this.course), this.componentContainers['courseFormat']);
}
/**
* Detect changes on input properties.
*/
ngOnChanges(changes: {[name: string]: SimpleChange}) {
if (changes.sections && this.sections) {
if (!this.selectedSection) {
// There is no selected section yet, calculate which one to get.
this.cfDelegate.getCurrentSection(this.course, this.sections).then((section) => {
this.loaded = true;
this.sectionChanged(section);
});
} else {
// We have a selected section, but the list has changed. Search the section in the list.
let newSection;
for (let i = 0; i < this.sections.length; i++) {
let section = this.sections[i];
if (this.compareSections(section, this.selectedSection)) {
newSection = section;
break;
}
}
if (!newSection) {
// Section not found, calculate which one to use.
newSection = this.cfDelegate.getCurrentSection(this.course, this.sections);
}
this.sectionChanged(newSection);
}
}
if (changes.downloadEnabled && this.downloadEnabled) {
this.calculateSectionsStatus(false);
}
// Apply the changes to the components and call ngOnChanges if it exists.
for (let type in this.componentInstances) {
let instance = this.componentInstances[type];
for (let name in changes) {
instance[name] = changes[name].currentValue;
}
if (instance.ngOnChanges) {
instance.ngOnChanges(changes);
}
}
}
/**
* Create a component, add it to a container and set the input data.
*
* @param {string} type The "type" of the component.
* @param {any} componentClass The class of the component to create.
* @param {ViewContainerRef} container The container to add the component to.
* @return {boolean} Whether the component was successfully created.
*/
protected createComponent(type: string, componentClass: any, container: ViewContainerRef) : boolean {
if (!componentClass || !container) {
// No component to instantiate or container doesn't exist right now.
return false;
}
if (this.componentInstances[type] && container === this.componentContainers[type]) {
// Component already instantiated and the component hasn't been destroyed, nothing to do.
return true;
}
try {
// Create the component and add it to the container.
const factory = this.factoryResolver.resolveComponentFactory(componentClass),
componentRef = container.createComponent(factory);
this.componentContainers[type] = container;
this.componentInstances[type] = componentRef.instance;
// Set the Input data.
this.componentInstances[type].course = this.course;
this.componentInstances[type].sections = this.sections;
this.componentInstances[type].downloadEnabled = this.downloadEnabled;
this.cdr.detectChanges(); // The instances are used in ngIf, tell Angular that something has changed.
return true;
} catch(ex) {
this.logger.error('Error creating component', type, ex);
return false;
}
}
/**
* Function called when selected section changes.
*
* @param {any} newSection The new selected section.
*/
sectionChanged(newSection: any) {
let previousValue = this.selectedSection;
this.selectedSection = newSection;
// If there is a component to render the current section, update its section.
if (this.componentInstances.singleSection) {
this.componentInstances.singleSection.section = this.selectedSection;
if (this.componentInstances.singleSection.ngOnChanges) {
this.componentInstances.singleSection.ngOnChanges({
section: new SimpleChange(previousValue, newSection, typeof previousValue != 'undefined')
});
}
}
}
/**
* Compare if two sections are equal.
*
* @param {any} s1 First section.
* @param {any} s2 Second section.
* @return {boolean} Whether they're equal.
*/
compareSections(s1: any, s2: any) : boolean {
return s1 && s2 ? s1.id === s2.id : s1 === s2;
}
/**
* Calculate the status of sections.
*
* @param {boolean} refresh [description]
*/
protected calculateSectionsStatus(refresh?: boolean) : void {
this.courseHelper.calculateSectionsStatus(this.sections, this.course.id, refresh).catch(() => {
// Ignore errors (shouldn't happen).
});
}
/**
* Confirm and prefetch a section. If the section is "all sections", prefetch all the sections.
*
* @param {Event} e Click event.
* @param {any} section Section to download.
*/
prefetch(e: Event, section: any) : void {
e.preventDefault();
e.stopPropagation();
section.isCalculating = true;
this.courseHelper.confirmDownloadSizeSection(this.course.id, section, this.sections).then(() => {
this.prefetchSection(section, true);
}, (error) => {
// User cancelled or there was an error calculating the size.
if (error) {
this.domUtils.showErrorModal(error);
}
}).finally(() => {
section.isCalculating = false;
});
}
/**
* Prefetch a section.
*
* @param {any} section The section to download.
* @param {boolean} [manual] Whether the prefetch was started manually or it was automatically started because all modules
* are being downloaded.
*/
protected prefetchSection(section: any, manual?: boolean) {
this.courseHelper.prefetchSection(section, this.course.id, this.sections).catch((error) => {
// Don't show error message if it's an automatic download.
if (!manual) {
return;
}
this.domUtils.showErrorModalDefault(error, 'core.course.errordownloadingsection', true);
});
}
/**
* Component destroyed.
*/
ngOnDestroy() {
if (this.sectionStatusObserver) {
this.sectionStatusObserver.off();
}
}
}

View File

@ -0,0 +1,3 @@
<a *ngIf="completion" (click)="completionClicked($event)">
<img [src]="completionImage" [alt]="completionDescription" [title]="completionDescription">
</a>

View File

@ -0,0 +1,7 @@
core-course-module-completion a {
img {
padding: 5px;
width: 30px;
vertical-align: middle;
}
}

View File

@ -0,0 +1,150 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
/**
* Component to handle activity completion. It shows a checkbox with the current status, and allows manually changing
* the completion if it's allowed.
*
* Example usage:
*
* <core-course-module-completion [completion]="module.completionstatus" [moduleName]="module.name"
* (completionChanged)="completionChanged()"></core-course-module-completion>
*/
@Component({
selector: 'core-course-module-completion',
templateUrl: 'module-completion.html'
})
export class CoreCourseModuleCompletionComponent implements OnChanges {
@Input() completion: any; // The completion status.
@Input() moduleName?: string; // The name of the module this completion affects.
@Output() completionChanged?: EventEmitter<void>; // Will emit an event when the completion changes.
completionImage: string;
completionDescription: string;
constructor(private textUtils: CoreTextUtilsProvider, private translate: TranslateService,
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider) {
this.completionChanged = new EventEmitter();
}
/**
* Detect changes on input properties.
*/
ngOnChanges(changes: {[name: string]: SimpleChange}) {
if (changes.completion && this.completion) {
this.showStatus();
}
}
/**
* Completion clicked.
*
* @param {Event} e The click event.
*/
completionClicked(e: Event) : void {
if (this.completion) {
if (typeof this.completion.cmid == 'undefined' || this.completion.tracking !== 1) {
return;
}
e.preventDefault();
e.stopPropagation();
let modal = this.domUtils.showModalLoading(),
params = {
cmid: this.completion.cmid,
completed: this.completion.state === 1 ? 0 : 1
},
currentSite = this.sitesProvider.getCurrentSite();
currentSite.write('core_completion_update_activity_completion_status_manually', params).then((response) => {
if (!response.status) {
return Promise.reject(null);
}
this.completionChanged.emit();
}).catch((error) => {
this.domUtils.showErrorModalDefault(error, 'core.errorchangecompletion', true);
}).finally(() => {
modal.dismiss();
});
}
}
/**
* Set image and description to show as completion icon.
*/
protected showStatus() : void {
let langKey,
moduleName = this.moduleName || '',
image;
if (this.completion.tracking === 1 && this.completion.state === 0) {
image = 'completion-manual-n';
langKey = 'core.completion-alt-manual-n';
} else if (this.completion.tracking === 1 && this.completion.state === 1) {
image = 'completion-manual-y';
langKey = 'core.completion-alt-manual-y';
} else if (this.completion.tracking === 2 && this.completion.state === 0) {
image = 'completion-auto-n';
langKey = 'core.completion-alt-auto-n';
} else if (this.completion.tracking === 2 && this.completion.state === 1) {
image = 'completion-auto-y';
langKey = 'core.completion-alt-auto-y';
} else if (this.completion.tracking === 2 && this.completion.state === 2) {
image = 'completion-auto-pass';
langKey = 'core.completion-alt-auto-pass';
} else if (this.completion.tracking === 2 && this.completion.state === 3) {
image = 'completion-auto-fail';
langKey = 'core.completion-alt-auto-fail';
}
if (image) {
if (this.completion.overrideby > 0) {
image += '-override';
}
this.completionImage = 'assets/img/completion/' + image + '.svg';
}
if (moduleName) {
this.textUtils.formatText(moduleName, true, true, 50).then((modNameFormatted) => {
let promise;
if (this.completion.overrideby > 0) {
langKey += '-override';
// @todo: Get user profile.
// promise = $mmUser.getProfile(scope.completion.overrideby, scope.completion.courseId, true).then(function(profile) {
// return {
// overrideuser: profile.fullname,
// modname: modNameFormatted
// };
// });
} else {
promise = Promise.resolve(modNameFormatted);
}
return promise.then((translateParams) => {
this.completionDescription = this.translate.instant(langKey, {$a: translateParams});
});
});
}
}
}

View File

@ -0,0 +1,6 @@
<ion-card *ngIf="description">
<ion-item text-wrap>
<core-format-text [text]="description" [component]="component" [componentId]="componentId" [maxHeight]="showFull && showFull !== 'false' ? 0 : 120" fullOnClick="true"></core-format-text>
<ion-note *ngIf="note" item-end>{{ note }}</ion-note>
</ion-item>
</ion-card>

View File

@ -0,0 +1,45 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input } from '@angular/core';
/**
* Component to display the description of a module.
*
* This directive is meant to display a module description in a similar way throughout all the app.
*
* You can add a note at the right side of the description by using the 'note' attribute.
*
* You can also pass a component and componentId to be used in format-text.
*
* Module descriptions are shortened by default, allowing the user to see the full description by clicking in it.
* If you want the whole description to be shown you can use the 'showFull' attribute.
*
* Example usage:
*
* <core-course-module-description [description]="myDescription"></core-course-module-description
*/
@Component({
selector: 'core-course-module-description',
templateUrl: 'module-description.html'
})
export class CoreCourseModuleDescriptionComponent {
@Input() description: string; // The description to display.
@Input() note?: string; // A note to display along with the description.
@Input() component?: string; // Component for format text directive.
@Input() componentId?: string|number; // Component ID to use in conjunction with the component.
@Input() showFull?: string|boolean; // Whether to always display the full description.
constructor() {}
}

View File

@ -0,0 +1,22 @@
<a *ngIf="module && module.visibleoncoursepage !== 0" ion-item text-wrap id="core-course-module-{{module.id}}" class="core-course-module-handler {{module.handlerData.class}}" (click)="moduleClicked($event)" [ngClass]="{'item-media': module.handlerData.icon, 'core-not-clickable': !module.handlerData.action || !module.uservisible === false, 'item-dimmed': module.visible === 0 || module.uservisible === false}" title="{{ module.handlerData.title }}" detail-none>
<img item-start *ngIf="module.handlerData.icon" [src]="module.handlerData.icon" alt="" role="presentation" class="core-module-icon">
<core-format-text [text]="module.handlerData.title"></core-format-text>
<div float-end *ngIf="module.uservisible !== false && ((module.handlerData.buttons && module.handlerData.buttons.length > 0) || spinner || module.completionstatus)" class="buttons core-module-buttons" [ngClass]="{'core-button-completion': module.completionstatus}">
<core-course-module-completion *ngIf="module.completionstatus" [completion]="module.completionstatus" [moduleName]="module.name" (completionChanged)="completionChanged.emit()"></core-course-module-completion>
<button ion-button icon-only clear *ngFor="let button of module.handlerData.buttons" [hidden]="button.hidden" (click)="buttonClicked($event, button)" color="dark" class="core-animate-show-hide" [attr.aria-label]="button.label | translate">
<ion-icon [name]="button.icon" [ios]="button.iosIcon || ''" [md]="button.mdIcon || ''"></ion-icon>
</button>
<ion-spinner *ngIf="module.handlerData.spinner" class="core-animate-show-hide"></ion-spinner>
</div>
<div *ngIf="module.visible === 0 || module.availabilityinfo">
<ion-badge item-end *ngIf="module.visible === 0">{{ 'core.course.hiddenfromstudents' | translate }}</ion-badge>
<ion-badge item-end *ngIf="module.availabilityinfo"><core-format-text [text]="module.availabilityinfo"></core-format-text></ion-badge>
</div>
<core-format-text *ngIf="module.description" maxHeight="80" [text]="module.description"></core-format-text>
</a>

View File

@ -0,0 +1,30 @@
core-course-module {
a.core-course-module-handler {
align-items: flex-start;
item-inner {
padding-right: 0;
}
}
.core-module-icon {
align-items: flex-start;
}
.core-module-buttons {
display: flex;
flex-flow: row;
align-items: center;
z-index: 1;
cursor: pointer;
pointer-events: auto;
position: absolute;
right: 0;
top: 4px;
.spinner {
right: 7px;
position: absolute;
}
}
}

View File

@ -0,0 +1,71 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreCourseModuleHandlerButton } from '../../providers/module-delegate';
/**
* Component to display a module entry in a list of modules.
*
* Example usage:
*
* <core-course-module [module]="module" [courseId]="courseId" (completionChanged)="onCompletionChange()"></core-course-module>
*/
@Component({
selector: 'core-course-module',
templateUrl: 'module.html'
})
export class CoreCourseModuleComponent implements OnInit {
@Input() module: any; // The module to render.
@Input() courseId: number; // The course the module belongs to.
@Output() completionChanged?: EventEmitter<void>; // Will emit an event when the module completion changes.
constructor(private navCtrl: NavController) {
this.completionChanged = new EventEmitter();
}
/**
* Component being initialized.
*/
ngOnInit() {
// Handler data must be defined. If it isn't, set it to prevent errors.
if (this.module && !this.module.handlerData) {
this.module.handlerData = {};
}
}
/**
* Function called when the module is clicked.
*
* @param {Event} event Click event.
*/
moduleClicked(event: Event) {
if (this.module.uservisible !== false && this.module.handlerData.action) {
this.module.handlerData.action(event, this.navCtrl, this.module, this.courseId);
}
}
/**
* Function called when a button is clicked.
*
* @param {Event} event Click event.
* @param {CoreCourseModuleHandlerButton} button The clicked button.
*/
buttonClicked(event: Event, button: CoreCourseModuleHandlerButton) {
if (button && button.action) {
button.action(event, this.navCtrl, this.module, this.courseId);
}
}
}

View File

@ -0,0 +1,18 @@
<div padding>
<core-course-module-description [description]="module.description"></core-course-module-description>
<h2 *ngIf="!isDisabledInSite && isSupportedByTheApp">{{ 'core.whoops' | translate }}</h2>
<h2 *ngIf="isDisabledInSite || !isSupportedByTheApp">{{ 'core.uhoh' | translate }}</h2>
<p class="core-big" *ngIf="isDisabledInSite">{{ 'core.course.activitydisabled' | translate }}</p>
<p class="core-big" *ngIf="!isDisabledInSite && isSupportedByTheApp">{{ 'core.course.activitynotyetviewablesiteupgradeneeded' | translate }}</p>
<p class="core-big" *ngIf="!isDisabledInSite && !isSupportedByTheApp">{{ 'core.course.activitynotyetviewableremoteaddon' | translate }}</p>
<p *ngIf="isDisabledInSite || !isSupportedByTheApp"><strong>{{ 'core.course.askadmintosupport' | translate }}</strong></p>
<div *ngIf="module.url">
<p><strong>{{ 'core.course.useactivityonbrowser' | translate }}</strong></p>
<a ion-button block icon-end [href]="module.url" core-link>
{{ 'core.openinbrowser' | translate }}
<ion-icon name="open"></ion-icon>
</a>
</div>
</div>

View File

@ -0,0 +1,48 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, OnInit } from '@angular/core';
import { IonicPage, NavParams } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
import { CoreCourseProvider } from '../../providers/course';
import { CoreCourseModuleDelegate } from '../../providers/module-delegate';
/**
* Component that displays info about an unsupported module.
*/
@Component({
selector: 'core-course-unsupported-module',
templateUrl: 'unsupported-module.html',
})
export class CoreCourseUnsupportedModuleComponent implements OnInit {
@Input() course: any; // The course to module belongs to.
@Input() module: any; // The module to render.
isDisabledInSite: boolean;
isSupportedByTheApp: boolean;
moduleName: string;
constructor(navParams: NavParams, private translate: TranslateService, private textUtils: CoreTextUtilsProvider,
private courseProvider: CoreCourseProvider, private moduleDelegate: CoreCourseModuleDelegate) {}
/**
* Component being initialized.
*/
ngOnInit() {
this.isDisabledInSite = this.moduleDelegate.isModuleDisabledInSite(this.module.modname);
this.isSupportedByTheApp = this.moduleDelegate.hasHandler(this.module.modname);
this.moduleName = this.courseProvider.translateModuleName(this.module.modname);
}
}

View File

@ -0,0 +1,45 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreCourseProvider } from './providers/course';
import { CoreCourseHelperProvider } from './providers/helper';
import { CoreCourseFormatDelegate } from './providers/format-delegate';
import { CoreCourseModuleDelegate } from './providers/module-delegate';
import { CoreCourseModulePrefetchDelegate } from './providers/module-prefetch-delegate';
import { CoreCourseFormatDefaultHandler } from './providers/default-format';
import { CoreCourseFormatSingleActivityModule } from './formats/singleactivity/singleactivity.module';
import { CoreCourseFormatSocialModule } from './formats/social/social.module';
import { CoreCourseFormatTopicsModule} from './formats/topics/topics.module';
import { CoreCourseFormatWeeksModule } from './formats/weeks/weeks.module';
@NgModule({
declarations: [],
imports: [
CoreCourseFormatSingleActivityModule,
CoreCourseFormatTopicsModule,
CoreCourseFormatWeeksModule,
CoreCourseFormatSocialModule
],
providers: [
CoreCourseProvider,
CoreCourseHelperProvider,
CoreCourseFormatDelegate,
CoreCourseModuleDelegate,
CoreCourseModulePrefetchDelegate,
CoreCourseFormatDefaultHandler
],
exports: []
})
export class CoreCourseModule {}

View File

@ -0,0 +1,119 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, OnChanges, ViewContainerRef, ComponentFactoryResolver, ChangeDetectorRef,
SimpleChange } from '@angular/core';
import { CoreLoggerProvider } from '../../../../../providers/logger';
import { CoreCourseModuleDelegate } from '../../../providers/module-delegate';
import { CoreCourseUnsupportedModuleComponent } from '../../../components/unsupported-module/unsupported-module';
/**
* Component to display single activity format. It will determine the right component to use and instantiate it.
*
* The instantiated component will receive the course and the module as inputs.
*/
@Component({
selector: 'core-course-format-single-activity',
template: ''
})
export class CoreCourseFormatSingleActivityComponent implements OnChanges {
@Input() course: any; // The course to render.
@Input() sections: any[]; // List of course sections.
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
protected logger: any;
protected module: any;
protected componentInstance: any;
constructor(logger: CoreLoggerProvider, private viewRef: ViewContainerRef, private factoryResolver: ComponentFactoryResolver,
private cdr: ChangeDetectorRef, private moduleDelegate: CoreCourseModuleDelegate) {
this.logger = logger.getInstance('CoreCourseFormatSingleActivityComponent');
}
/**
* Detect changes on input properties.
*/
ngOnChanges(changes: {[name: string]: SimpleChange}) {
if (this.course && this.sections && this.sections.length) {
// In single activity the module should only have 1 section and 1 module. Get the module.
let module = this.sections[0] && this.sections[0].modules && this.sections[0].modules[0];
if (module && !this.componentInstance) {
// We haven't created the component yet. Create it now.
this.createComponent(module);
}
if (this.componentInstance && this.componentInstance.ngOnChanges) {
// Call ngOnChanges of the component.
let newChanges: {[name: string]: SimpleChange} = {};
// Check if course has changed.
if (changes.course) {
newChanges.course = changes.course
this.componentInstance.course = this.course;
}
// Check if module has changed.
if (changes.sections && module != this.module) {
newChanges.module = {
currentValue: module,
firstChange: changes.sections.firstChange,
previousValue: this.module,
isFirstChange: () => {
return newChanges.module.firstChange;
}
};
this.componentInstance.module = module;
this.module = module;
}
if (Object.keys(newChanges).length) {
this.componentInstance.ngOnChanges(newChanges);
}
}
}
}
/**
* Create the component, add it to the container and set the input data.
*
* @param {any} module The module.
* @return {boolean} Whether the component was successfully created.
*/
protected createComponent(module: any) : boolean {
let componentClass = this.moduleDelegate.getMainComponent(this.course, module) || CoreCourseUnsupportedModuleComponent;
if (!componentClass) {
// No component to instantiate.
return false;
}
try {
// Create the component and add it to the container.
const factory = this.factoryResolver.resolveComponentFactory(componentClass),
componentRef = this.viewRef.createComponent(factory);
this.componentInstance = componentRef.instance;
// Set the Input data.
this.componentInstance.courseId = this.course.id;
this.componentInstance.module = module;
// this.cdr.detectChanges(); // The instances are used in ngIf, tell Angular that something has changed.
return true;
} catch(ex) {
this.logger.error('Error creating component', ex);
return false;
}
}
}

View File

@ -0,0 +1,83 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreCourseFormatHandler } from '../../../providers/format-delegate';
import { CoreCourseFormatSingleActivityComponent } from '../components/format';
/**
* Handler to support singleactivity course format.
*/
@Injectable()
export class CoreCourseFormatSingleActivityHandler implements CoreCourseFormatHandler {
name = 'singleactivity';
constructor() {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Whether it allows seeing all sections at the same time. Defaults to true.
*
* @param {any} course The course to check.
* @type {boolean} Whether it can view all sections.
*/
canViewAllSections(course: any) : boolean {
return false;
}
/**
* Get the title to use in course page. If not defined, course fullname.
* This function will be called without sections first, and then call it again when the sections are retrieved.
*
* @param {any} course The course.
* @param {any[]} [sections] List of sections.
* @return {string} Title.
*/
getCourseTitle(course: any, sections?: any[]) : string {
if (sections && sections[0] && sections[0].modules && sections[0].modules[0]) {
return sections[0].modules[0].name;
}
return course.fullname || '';
}
/**
* Whether the default section selector should be displayed. Defaults to true.
*
* @param {any} course The course to check.
* @type {boolean} Whether the default section selector should be displayed.
*/
displaySectionSelector(course: any) : boolean {
return false;
}
/**
* Return the Component to use to display the course format instead of using the default one.
* Use it if you want to display a format completely different from the default one.
* If you want to customize the default format there are several methods to customize parts of it.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getCourseFormatComponent(course: any) : any {
return CoreCourseFormatSingleActivityComponent;
}
}

View File

@ -0,0 +1,40 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreCourseFormatSingleActivityComponent } from './components/format';
import { CoreCourseFormatSingleActivityHandler } from './providers/handler';
import { CoreCourseFormatDelegate } from '../../providers/format-delegate';
@NgModule({
declarations: [
CoreCourseFormatSingleActivityComponent
],
imports: [
],
providers: [
CoreCourseFormatSingleActivityHandler
],
exports: [
CoreCourseFormatSingleActivityComponent
],
entryComponents: [
CoreCourseFormatSingleActivityComponent
]
})
export class CoreCourseFormatSingleActivityModule {
constructor(formatDelegate: CoreCourseFormatDelegate, handler: CoreCourseFormatSingleActivityHandler) {
formatDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,25 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreCourseFormatSingleActivityHandler } from '../../singleactivity/providers/handler';
/**
* Handler to support social course format.
* This format is like singleactivity in the mobile app, so we'll use the same implementation for both.
*/
@Injectable()
export class CoreCourseFormatSocialHandler extends CoreCourseFormatSingleActivityHandler {
name = 'social';
}

View File

@ -0,0 +1,32 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreCourseFormatSocialHandler } from './providers/handler';
import { CoreCourseFormatDelegate } from '../../providers/format-delegate';
@NgModule({
declarations: [],
imports: [
],
providers: [
CoreCourseFormatSocialHandler
],
exports: []
})
export class CoreCourseFormatSocialModule {
constructor(formatDelegate: CoreCourseFormatDelegate, handler: CoreCourseFormatSocialHandler) {
formatDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,35 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreCourseFormatHandler } from '../../../providers/format-delegate';
/**
* Handler to support topics course format.
*/
@Injectable()
export class CoreCourseFormatTopicsHandler implements CoreCourseFormatHandler {
name = 'topics';
constructor() {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
}

View File

@ -0,0 +1,32 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreCourseFormatTopicsHandler } from './providers/handler';
import { CoreCourseFormatDelegate } from '../../providers/format-delegate';
@NgModule({
declarations: [],
imports: [
],
providers: [
CoreCourseFormatTopicsHandler
],
exports: []
})
export class CoreCourseFormatTopicsModule {
constructor(formatDelegate: CoreCourseFormatDelegate, handler: CoreCourseFormatTopicsHandler) {
formatDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,87 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreCourseFormatHandler } from '../../../providers/format-delegate';
import { CoreTimeUtilsProvider } from '../../../../../providers/utils/time';
import { CoreConstants } from '../../../../constants';
/**
* Handler to support weeks course format.
*/
@Injectable()
export class CoreCourseFormatWeeksHandler implements CoreCourseFormatHandler {
name = 'weeks';
constructor(private timeUtils: CoreTimeUtilsProvider) {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Given a list of sections, get the "current" section that should be displayed first.
*
* @param {any} course The course to get the title.
* @param {any[]} sections List of sections.
* @return {any|Promise<any>} Current section (or promise resolved with current section).
*/
getCurrentSection(course: any, sections: any[]) : any|Promise<any> {
let now = this.timeUtils.timestamp();
if (now < course.startdate || (course.enddate && now > course.enddate)) {
// Course hasn't started yet or it has ended already. Return the first section.
return sections[1];
}
for (let i = 0; i < sections.length; i++) {
let section = sections[i];
if (typeof section.section == 'undefined' || section.section < 1) {
continue;
}
let dates = this.getSectionDates(section, course.startdate);
if ((now >= dates.start) && (now < dates.end)) {
return section;
}
}
// The section wasn't found, return the first section.
return sections[1];
}
/**
* Return the start and end date of a section.
*
* @param {any} section The section to treat.
* @param {number} startDate The course start date (in seconds).
* @return {{start: number, end: number}} An object with the start and end date of the section.
*/
protected getSectionDates(section: any, startDate: number) : {start: number, end: number} {
// Hack alert. We add 2 hours to avoid possible DST problems. (e.g. we go into daylight savings and the date changes).
startDate = startDate + 7200;
let dates = {
start: startDate + (CoreConstants.SECONDS_WEEK * (section.section - 1)),
end: 0
};
dates.end = dates.start + CoreConstants.SECONDS_WEEK;
return dates;
}
}

View File

@ -0,0 +1,32 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreCourseFormatWeeksHandler } from './providers/handler';
import { CoreCourseFormatDelegate } from '../../providers/format-delegate';
@NgModule({
declarations: [],
imports: [
],
providers: [
CoreCourseFormatWeeksHandler
],
exports: []
})
export class CoreCourseFormatWeeksModule {
constructor(formatDelegate: CoreCourseFormatDelegate, handler: CoreCourseFormatWeeksHandler) {
formatDelegate.registerHandler(handler);
}
}

View File

@ -0,0 +1,23 @@
{
"activitydisabled": "Your organisation has disabled this activity in the mobile app.",
"activitynotyetviewableremoteaddon": "Your organisation installed a plugin that is not yet supported.",
"activitynotyetviewablesiteupgradeneeded": "Your organisation's Moodle installation needs to be updated.",
"allsections": "All sections",
"askadmintosupport": "Contact the site administrator and tell them you want to use this activity with the Moodle Mobile app.",
"confirmdeletemodulefiles": "Are you sure you want to delete these files?",
"confirmdownload": "You are about to download {{size}}. Are you sure you want to continue?",
"confirmdownloadunknownsize": "It was not possible to calculate the size of the download. Are you sure you want to continue?",
"confirmpartialdownloadsize": "You are about to download <strong>at least</strong> {{size}}. Are you sure you want to continue?",
"contents": "Contents",
"couldnotloadsectioncontent": "Could not load the section content. Please try again later.",
"couldnotloadsections": "Could not load the sections. Please try again later.",
"downloadcourse": "Download course",
"errordownloadingcourse": "Error downloading course.",
"errordownloadingsection": "Error downloading section.",
"errorgetmodule": "Error getting activity data.",
"hiddenfromstudents": "Hidden from students",
"nocontentavailable": "No content available at the moment.",
"overriddennotice": "Your final grade from this activity was manually adjusted.",
"sections": "Sections",
"useactivityonbrowser": "You can still use it using your device's web browser."
}

View File

@ -0,0 +1,26 @@
<ion-header>
<ion-navbar>
<ion-title><core-format-text [text]="title"></core-format-text></ion-title>
<ion-buttons end>
<core-context-menu>
<core-context-menu-item [priority]="900" [content]="'core.settings.enabledownloadsection' | translate" (action)="toggleDownload()" [iconAction]="downloadEnabledIcon"></core-context-menu-item>
<core-context-menu-item [priority]="850" [content]="'core.course.downloadcourse' | translate" (action)="prefetchCourse()" [iconAction]="prefetchCourseData.prefetchCourseIcon" [closeOnClick]="false"></core-context-menu-item>
</core-context-menu>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<ion-refresher [enabled]="dataLoaded" (ionRefresh)="doRefresh($event)">
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher>
<core-loading [hideUntil]="dataLoaded">
<!-- @todo: Use core-tabs or a new component. core-tabs might initialize all tabs at start, so we might require a new component. -->
<div class="core-tabs-bar">
<a aria-selected="true">{{ 'core.course.contents' | translate }}</a>
<a *ngFor="let handler of courseHandlers">{{ handler.data.title || translate }}</a>
</div>
<core-course-format [course]="course" [sections]="sections" [downloadEnabled]="downloadEnabled" (completionChanged)="onCompletionChange()"></core-course-format>
</core-loading>
</ion-content>

View File

@ -0,0 +1,35 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreCourseSectionPage } from './section';
import { CoreComponentsModule } from '../../../../components/components.module';
import { CoreDirectivesModule } from '../../../../directives/directives.module';
import { CoreCourseComponentsModule } from '../../components/components.module';
@NgModule({
declarations: [
CoreCourseSectionPage,
],
imports: [
CoreComponentsModule,
CoreDirectivesModule,
CoreCourseComponentsModule,
IonicPageModule.forChild(CoreCourseSectionPage),
TranslateModule.forChild()
],
})
export class CoreCourseSectionPageModule {}

View File

@ -0,0 +1,24 @@
page-core-course-section {
.core-tabs-bar {
@include position(null, null, 0, 0);
z-index: $z-index-toolbar;
display: flex;
width: 100%;
background: $core-top-tabs-background;
> a {
@extend .tab-button;
background: $core-top-tabs-background;
color: $core-top-tabs-color !important;
border-bottom: 1px solid $core-top-tabs-border;
font-size: 1.6rem;
&[aria-selected=true] {
color: $core-top-tabs-color-active !important;
border-bottom: 2px solid $core-top-tabs-color-active;
}
}
}
}

View File

@ -0,0 +1,274 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, ViewChild, OnDestroy } from '@angular/core';
import { IonicPage, NavParams, Content } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreEventsProvider } from '../../../../providers/events';
import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
import { CoreCourseProvider } from '../../providers/course';
import { CoreCourseHelperProvider } from '../../providers/helper';
import { CoreCourseFormatDelegate } from '../../providers/format-delegate';
import { CoreCoursesDelegate, CoreCoursesHandlerToDisplay } from '../../../courses/providers/delegate';
import { CoreCoursesProvider } from '../../../courses/providers/courses';
/**
* Page that displays the list of courses the user is enrolled in.
*/
@IonicPage({segment: 'core-course-section'})
@Component({
selector: 'page-core-course-section',
templateUrl: 'section.html',
})
export class CoreCourseSectionPage implements OnDestroy {
@ViewChild(Content) content: Content;
title: string;
course: any;
sections: any[];
courseHandlers: CoreCoursesHandlerToDisplay[];
dataLoaded: boolean;
downloadEnabled: boolean;
downloadEnabledIcon: string = 'square-outline'; // Disabled by default.
prefetchCourseData = {
prefetchCourseIcon: 'spinner'
};
protected moduleId;
protected completionObserver;
protected courseStatusObserver;
protected isDestroyed = false;
constructor(navParams: NavParams, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider,
private courseFormatDelegate: CoreCourseFormatDelegate, private coursesDelegate: CoreCoursesDelegate,
private translate: TranslateService, private courseHelper: CoreCourseHelperProvider, eventsProvider: CoreEventsProvider,
private textUtils: CoreTextUtilsProvider, private coursesProvider: CoreCoursesProvider,
sitesProvider: CoreSitesProvider) {
this.course = navParams.get('course');
this.moduleId = navParams.get('moduleId');
// Get the title to display. We dont't have sections yet.
this.title = courseFormatDelegate.getCourseTitle(this.course);
this.completionObserver = eventsProvider.on(CoreEventsProvider.COMPLETION_MODULE_VIEWED, (data) => {
if (data && data.courseId == this.course.id) {
this.refreshAfterCompletionChange();
}
});
// Listen for changes in course status.
this.courseStatusObserver = eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.prefetchCourseData.prefetchCourseIcon = this.courseHelper.getCourseStatusIconFromStatus(data.status);
}
}, sitesProvider.getCurrentSiteId());
}
/**
* View loaded.
*/
ionViewDidLoad() {
this.loadData().finally(() => {
this.dataLoaded = true;
delete this.moduleId; // Only load module automatically the first time.
// Determine the course prefetch status.
this.determineCoursePrefetchIcon().then(() => {
if (this.prefetchCourseData.prefetchCourseIcon == 'spinner') {
// Course is being downloaded. Get the download promise.
const promise = this.courseHelper.getCourseDownloadPromise(this.course.id);
if (promise) {
// There is a download promise. Show an error if it fails.
promise.catch((error) => {
if (!this.isDestroyed) {
this.domUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
}
});
} else {
// No download, this probably means that the app was closed while downloading. Set previous status.
this.courseProvider.setCoursePreviousStatus(this.course.id).then((status) => {
this.prefetchCourseData.prefetchCourseIcon = this.courseHelper.getCourseStatusIconFromStatus(status);
});
}
}
});
});
}
/**
* Fetch and load all the data required for the view.
*/
protected loadData(refresh?: boolean) {
// First of all, get the course because the data might have changed.
return this.coursesProvider.getUserCourse(this.course.id).then((course) => {
let promises = [],
promise;
this.course = course;
// Get the completion status.
if (this.course.enablecompletion === false) {
// Completion not enabled.
promise = Promise.resolve({});
} else {
promise = this.courseProvider.getActivitiesCompletionStatus(this.course.id).catch(() => {
// It failed, don't use completion.
return {};
});
}
promises.push(promise.then((completionStatus) => {
// Get all the sections.
promises.push(this.courseProvider.getSections(this.course.id, false, true).then((sections) => {
this.courseHelper.addHandlerDataForModules(sections, this.course.id, this.moduleId, completionStatus);
// Format the name of each section and check if it has content.
this.sections = sections.map((section) => {
this.textUtils.formatText(section.name.trim(), true, true).then((name) => {
section.formattedName = name;
});
section.hasContent = this.courseHelper.sectionHasContent(section);
return section;
});
if (this.courseFormatDelegate.canViewAllSections(this.course)) {
// Add a fake first section (all sections).
this.sections.unshift({
name: this.translate.instant('core.course.allsections'),
id: CoreCourseProvider.ALL_SECTIONS_ID
});
}
// Get the title again now that we have sections.
this.title = this.courseFormatDelegate.getCourseTitle(this.course, this.sections);
}));
}));
// Load the course handlers.
promises.push(this.coursesDelegate.getHandlersToDisplay(this.course, refresh, false).then((handlers) => {
this.courseHandlers = handlers;
}));
return Promise.all(promises).catch((error) => {
this.domUtils.showErrorModalDefault(error, 'core.course.couldnotloadsectioncontent', true);
});
});
}
/**
* Refresh the data.
*
* @param {any} refresher Refresher.
*/
doRefresh(refresher: any) {
this.invalidateData().finally(() => {
this.loadData(true).finally(() => {
refresher.complete();
});
});
}
/**
* The completion of any of the modules have changed.
*/
onCompletionChange() {
this.invalidateData().finally(() => {
this.refreshAfterCompletionChange();
});
}
/**
* Invalidate the data.
*/
protected invalidateData() {
let promises = [];
promises.push(this.courseProvider.invalidateSections(this.course.id));
promises.push(this.coursesProvider.invalidateUserCourses());
promises.push(this.courseFormatDelegate.invalidateData(this.course, this.sections));
// if ($scope.sections) {
// promises.push($mmCoursePrefetchDelegate.invalidateCourseUpdates(courseId));
// }
return Promise.all(promises);
}
/**
* Refresh list after a completion change since there could be new activities.
*/
protected refreshAfterCompletionChange() {
// Save scroll position to restore it once done.
let scrollElement = this.content.getScrollElement(),
scrollTop = scrollElement.scrollTop || 0,
scrollLeft = scrollElement.scrollLeft || 0;
this.dataLoaded = false;
this.content.scrollToTop(); // Scroll top so the spinner is seen.
this.loadData().finally(() => {
this.dataLoaded = true;
this.content.scrollTo(scrollLeft, scrollTop);
});
}
/**
* Determines the prefetch icon of the course.
*/
protected determineCoursePrefetchIcon() {
return this.courseHelper.getCourseStatusIcon(this.course.id).then((icon) => {
this.prefetchCourseData.prefetchCourseIcon = icon;
});
}
/**
* Prefetch the whole course.
*/
prefetchCourse() {
this.courseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course, this.sections, this.courseHandlers)
.then((downloaded) => {
if (downloaded && this.downloadEnabled) {
// Recalculate the status.
this.courseHelper.calculateSectionsStatus(this.sections, this.course.id).catch(() => {
// Ignore errors (shouldn't happen).
});
}
}).catch((error) => {
if (!this.isDestroyed) {
this.domUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
}
});
}
/**
* Toggle download enabled.
*/
toggleDownload() {
this.downloadEnabled = !this.downloadEnabled;
this.downloadEnabledIcon = this.downloadEnabled ? 'checkbox-outline' : 'square-outline';
}
/**
* Page destroyed.
*/
ngOnDestroy() {
this.isDestroyed = true;
if (this.completionObserver) {
this.completionObserver.off();
}
}
}

View File

@ -0,0 +1,15 @@
<ion-header>
<ion-navbar>
<ion-title><core-format-text [text]="module.name"></core-format-text></ion-title>
<ion-buttons end>
<core-context-menu>
<core-context-menu-item [priority]="900" *ngIf="module.url" [href]="module.url" [content]="'core.openinbrowser' | translate" [iconAction]="'open'"></core-context-menu-item>
<core-context-menu-item [priority]="800" *ngIf="module.description" [content]="'core.moduleintro' | translate" (action)="expandDescription()" [iconAction]="'arrow-forward'"></core-context-menu-item>
</core-context-menu>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<core-course-unsupported-module [module]="module"></core-course-unsupported-module>
</ion-content>

View File

@ -0,0 +1,35 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreCourseUnsupportedModulePage } from './unsupported-module';
import { CoreComponentsModule } from '../../../../components/components.module';
import { CoreDirectivesModule } from '../../../../directives/directives.module';
import { CoreCourseComponentsModule } from '../../components/components.module';
@NgModule({
declarations: [
CoreCourseUnsupportedModulePage,
],
imports: [
CoreComponentsModule,
CoreDirectivesModule,
CoreCourseComponentsModule,
IonicPageModule.forChild(CoreCourseUnsupportedModulePage),
TranslateModule.forChild()
],
})
export class CoreCourseUnsupportedModulePageModule {}

View File

@ -0,0 +1,42 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component } from '@angular/core';
import { IonicPage, NavParams, NavController } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
/**
* Page that displays info about an unsupported module.
*/
@IonicPage({segment: 'core-course-unsupported-module'})
@Component({
selector: 'page-core-course-unsupported-module',
templateUrl: 'unsupported-module.html',
})
export class CoreCourseUnsupportedModulePage {
module: any;
constructor(navParams: NavParams, private translate: TranslateService, private textUtils: CoreTextUtilsProvider,
private navCtrl: NavController) {
this.module = navParams.get('module') || {};
}
/**
* Expand the description.
*/
expandDescription() {
this.textUtils.expandText(this.translate.instant('core.description'), this.module.description);
}
}

View File

@ -0,0 +1,727 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CoreEventsProvider } from '../../../providers/events';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSitesProvider } from '../../../providers/sites';
import { CoreTimeUtilsProvider } from '../../../providers/utils/time';
import { CoreUtilsProvider } from '../../../providers/utils/utils';
import { CoreSiteWSPreSets } from '../../../classes/site';
import { CoreConstants } from '../../constants';
/**
* Service that provides some features regarding a course.
*/
@Injectable()
export class CoreCourseProvider {
public static ALL_SECTIONS_ID = -1;
protected ROOT_CACHE_KEY = 'mmCourse:';
// Variables for database.
protected COURSE_STATUS_TABLE = 'course_status';
protected courseStatusTableSchema = {
name: this.COURSE_STATUS_TABLE,
columns: [
{
name: 'id',
type: 'INTEGER',
primaryKey: true
},
{
name: 'status',
type: 'TEXT',
notNull: true
},
{
name: 'previous',
type: 'TEXT'
},
{
name: 'updated',
type: 'INTEGER'
},
{
name: 'downloadTime',
type: 'INTEGER'
},
{
name: 'previousDownloadTime',
type: 'INTEGER'
}
]
};
protected logger;
protected CORE_MODULES = [
'assign', 'assignment', 'book', 'chat', 'choice', 'data', 'database', 'date', 'external-tool',
'feedback', 'file', 'folder', 'forum', 'glossary', 'ims', 'imscp', 'label', 'lesson', 'lti', 'page', 'quiz',
'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop'
];
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private eventsProvider: CoreEventsProvider,
private utils: CoreUtilsProvider, private timeUtils: CoreTimeUtilsProvider, private translate: TranslateService) {
this.logger = logger.getInstance('CoreCourseProvider');
this.sitesProvider.createTableFromSchema(this.courseStatusTableSchema);
}
/**
* Check if module completion could have changed. If it could have, trigger event. This function must be used,
* for example, after calling a "module_view" WS since it can change the module completion.
*
* @param {number} courseId Course ID.
* @param {any} completion Completion status of the module.
*/
checkModuleCompletion(courseId: number, completion: any) : void {
if (completion && completion.tracking === 2 && completion.state === 0) {
this.invalidateSections(courseId).finally(() => {
this.eventsProvider.trigger(CoreEventsProvider.COMPLETION_MODULE_VIEWED, {courseId: courseId});
});
}
}
/**
* Clear all courses status in a site.
*
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<void>} Promise resolved when all status are cleared.
*/
clearAllCoursesStatus(siteId?: string) : Promise<void> {
return this.sitesProvider.getSite(siteId).then((site) => {
this.logger.debug('Clear all course status for site ' + site.id);
return site.getDb().deleteRecords(this.COURSE_STATUS_TABLE).then(() => {
this.triggerCourseStatusChanged(-1, CoreConstants.NOT_DOWNLOADED, site.id);
});
});
}
/**
* Get completion status of all the activities in a course for a certain user.
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @param {number} [userId] User ID. If not defined, current user.
* @return {Promise<any>} Promise resolved with the completion statuses: object where the key is module ID.
*/
getActivitiesCompletionStatus(courseId: number, siteId?: string, userId?: number) : Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
userId = userId || site.getUserId();
this.logger.debug(`Getting completion status for user ${userId} in course ${courseId}`);
let params = {
courseid: courseId,
userid: userId
},
preSets = {
cacheKey: this.getActivitiesCompletionCacheKey(courseId, userId)
};
return site.read('core_completion_get_activities_completion_status', params, preSets).then((data) => {
if (data && data.statuses) {
return this.utils.arrayToObject(data.statuses, 'cmid');
}
return Promise.reject(null);
});
});
}
/**
* Get cache key for activities completion WS calls.
*
* @param {number} courseId Course ID.
* @param {number} userId User ID.
* @return {string} Cache key.
*/
protected getActivitiesCompletionCacheKey(courseId: number, userId: number) : string {
return this.ROOT_CACHE_KEY + 'activitiescompletion:' + courseId + ':' + userId;
}
/**
* Get the data stored for a course.
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved with the data.
*/
getCourseStatusData(courseId: number, siteId?: string) : Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
return site.getDb().getRecord(this.COURSE_STATUS_TABLE, {id: courseId}).then((entry) => {
if (!entry) {
return Promise.reject(null);
}
return entry;
});
});
}
/**
* Get a course status.
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<string>} Promise resolved with the status.
*/
getCourseStatus(courseId: number, siteId?: string) : Promise<string> {
return this.getCourseStatusData(courseId, siteId).then((entry) => {
return entry.status || CoreConstants.NOT_DOWNLOADED;
}).catch(() => {
return CoreConstants.NOT_DOWNLOADED;
});
}
/**
* Get a module from Moodle.
*
* @param {number} moduleId The module ID.
* @param {number} [courseId] The course ID. Recommended to speed up the process and minimize data usage.
* @param {number} [sectionId] The section ID.
* @param {boolean} [preferCache] True if shouldn't call WS if data is cached, false otherwise.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved with the module.
*/
getModule(moduleId: number, courseId?: number, sectionId?: number, preferCache?: boolean, ignoreCache?: boolean,
siteId?: string) : Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
let promise;
if (!courseId) {
// No courseId passed, try to retrieve it.
promise = this.getModuleBasicInfo(moduleId, siteId).then((module) => {
return module.course;
});
} else {
promise = Promise.resolve(courseId);
}
return promise.then((cid) => {
courseId = cid;
// Get the site.
return this.sitesProvider.getSite(siteId);
}).then((site) => {
// We have courseId, we can use core_course_get_contents for compatibility.
this.logger.debug(`Getting module ${moduleId} in course ${courseId}`);
let params = {
courseid: courseId,
options: [
{
name: 'cmid',
value: moduleId
}
]
},
preSets: any = {
cacheKey: this.getModuleCacheKey(moduleId),
omitExpires: preferCache
};
if (!preferCache && ignoreCache) {
preSets.getFromCache = 0;
preSets.emergencyCache = 0;
}
if (sectionId) {
params.options.push({
name: 'sectionid',
value: sectionId
});
}
return site.read('core_course_get_contents', params, preSets).catch(() => {
// Error getting the module. Try to get all contents (without filtering by module).
return this.getSections(courseId, false, false, preSets, siteId);
}).then((sections) => {
for (let i = 0; i < sections.length; i++) {
let section = sections[i];
for (let j = 0; j < section.modules.length; j++) {
let module = section.modules[j];
if (module.id == moduleId) {
module.course = courseId;
return module;
}
}
}
return Promise.reject(null);
});
});
}
/**
* Gets a module basic info by module ID.
*
* @param {number} moduleId Module ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved with the module's info.
*/
getModuleBasicInfo(moduleId: number, siteId?: string) : Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
let params = {
cmid: moduleId
},
preSets = {
cacheKey: this.getModuleCacheKey(moduleId)
};
return site.read('core_course_get_course_module', params, preSets).then((response) => {
if (response.warnings && response.warnings.length) {
return Promise.reject(response.warnings[0]);
} else if (response.cm) {
return response.cm;
}
return Promise.reject(null);
});
});
}
/**
* Gets a module basic grade info by module ID.
*
* @param {number} moduleId Module ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved with the module's grade info.
*/
getModuleBasicGradeInfo(moduleId: number, siteId?: string) : Promise<any> {
return this.getModuleBasicInfo(moduleId, siteId).then((info) => {
let grade = {
advancedgrading: info.advancedgrading || false,
grade: info.grade || false,
gradecat: info.gradecat || false,
gradepass: info.gradepass || false,
outcomes: info.outcomes || false,
scale: info.scale || false
};
if (grade.grade !== false || grade.advancedgrading !== false || grade.outcomes !== false) {
return grade;
}
return false;
});
}
/**
* Gets a module basic info by instance.
*
* @param {number} id Instance ID.
* @param {string} module Name of the module. E.g. 'glossary'.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved with the module's info.
*/
getModuleBasicInfoByInstance(id: number, module: string, siteId?: string) : Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
let params = {
instance: id,
module: module
},
preSets = {
cacheKey: this.getModuleBasicInfoByInstanceCacheKey(id, module)
};
return site.read('core_course_get_course_module_by_instance', params, preSets).then((response) => {
if (response.warnings && response.warnings.length) {
return Promise.reject(response.warnings[0]);
} else if (response.cm) {
return response.cm;
}
return Promise.reject(null);
});
});
}
/**
* Get cache key for get module by instance WS calls.
*
* @param {number} id Instance ID.
* @param {string} module Name of the module. E.g. 'glossary'.
* @return {string} Cache key.
*/
protected getModuleBasicInfoByInstanceCacheKey(id: number, module: string) : string {
return this.ROOT_CACHE_KEY + 'moduleByInstance:' + module + ':' + id;
}
/**
* Get cache key for module WS calls.
*
* @param {number} moduleId Module ID.
* @return {string} Cache key.
*/
protected getModuleCacheKey(moduleId: number) : string {
return this.ROOT_CACHE_KEY + 'module:' + moduleId;
}
/**
* Returns the source to a module icon.
*
* @param {string} moduleName The module name.
* @return {string} The IMG src.
*/
getModuleIconSrc(moduleName: string) : string {
if (this.CORE_MODULES.indexOf(moduleName) < 0) {
moduleName = 'external-tool';
}
return 'assets/img/mod/' + moduleName + '.svg';
}
/**
* Get the section ID a module belongs to.
*
* @param {number} moduleId The module ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<number>} Promise resolved with the section ID.
*/
getModuleSectionId(moduleId: number, siteId?: string) : Promise<number> {
// Try to get the section using getModuleBasicInfo.
return this.getModuleBasicInfo(moduleId, siteId).then((module) => {
return module.section;
});
}
/**
* Return a specific section.
*
* @param {number} courseId The course ID.
* @param {number} sectionId The section ID.
* @param {boolean} [excludeModules] Do not return modules, return only the sections structure.
* @param {boolean} [excludeContents] Do not return module contents (i.e: files inside a resource).
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved with the section.
*/
getSection(courseId: number, sectionId?: number, excludeModules?: boolean, excludeContents?: boolean, siteId?: string)
: Promise<any> {
if (sectionId < 0) {
return Promise.reject('Invalid section ID');
}
return this.getSections(courseId, excludeModules, excludeContents, undefined, siteId).then((sections) => {
for (let i = 0; i < sections.length; i++) {
if (sections[i].id == sectionId) {
return sections[i];
}
}
return Promise.reject('Unkown section');
});
}
/**
* Get the course sections.
*
* @param {number} courseId The course ID.
* @param {boolean} [excludeModules] Do not return modules, return only the sections structure.
* @param {boolean} [excludeContents] Do not return module contents (i.e: files inside a resource).
* @param {CoreSiteWSPreSets} [preSets] Presets to use.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise} The reject contains the error message, else contains the sections.
*/
getSections(courseId?: number, excludeModules?: boolean, excludeContents?: boolean, preSets?: CoreSiteWSPreSets,
siteId?: string) : Promise<any[]> {
return this.sitesProvider.getSite(siteId).then((site) => {
preSets = preSets || {};
preSets.cacheKey = this.getSectionsCacheKey(courseId);
preSets.getCacheUsingCacheKey = true; // This is to make sure users don't lose offline access when updating.
let params = {
courseid: courseId,
options: [
{
name: 'excludemodules',
value: excludeModules ? 1 : 0
},
{
name: 'excludecontents',
value: excludeContents ? 1 : 0
}
]
};
return site.read('core_course_get_contents', params, preSets).then((sections) => {
let siteHomeId = site.getSiteHomeId(),
showSections = true;
if (courseId == siteHomeId) {
showSections = site.getStoredConfig('numsections');
}
if (typeof showSections != 'undefined' && !showSections && sections.length > 0) {
// Get only the last section (Main menu block section).
sections.pop();
}
return sections;
});
});
}
/**
* Get cache key for section WS call.
*
* @param {number} courseId Course ID.
* @return {string} Cache key.
*/
protected getSectionsCacheKey(courseId) : string {
return this.ROOT_CACHE_KEY + 'sections:' + courseId;
}
/**
* Given a list of sections, returns the list of modules in the sections.
*
* @param {any[]} sections Sections.
* @return {any[]} Modules.
*/
getSectionsModules(sections: any[]) : any[] {
if (!sections || !sections.length) {
return [];
}
let modules = [];
sections.forEach((section) => {
if (section.modules) {
modules = modules.concat(section.modules);
}
});
return modules;
}
/**
* Invalidates module WS call.
*
* @param {number} moduleId Module ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateModule(moduleId: number, siteId?: string) : Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
return site.invalidateWsCacheForKey(this.getModuleCacheKey(moduleId));
});
}
/**
* Invalidates module WS call.
*
* @param {number} id Instance ID.
* @param {string} module Name of the module. E.g. 'glossary'.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateModuleByInstance(id: number, module: string, siteId?: string) : Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
return site.invalidateWsCacheForKey(this.getModuleBasicInfoByInstanceCacheKey(id, module));
});
}
/**
* Invalidates sections WS call.
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @param {number} [userId] User ID. If not defined, current user.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateSections(courseId: number, siteId?: string, userId?: number) : Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => {
let promises = [],
siteHomeId = site.getSiteHomeId();
userId = userId || site.getUserId();
promises.push(site.invalidateWsCacheForKey(this.getSectionsCacheKey(courseId)));
promises.push(site.invalidateWsCacheForKey(this.getActivitiesCompletionCacheKey(courseId, userId)));
if (courseId == siteHomeId) {
promises.push(site.invalidateConfig());
}
return Promise.all(promises);
});
}
/**
* Load module contents into module.contents if they aren't loaded already.
*
* @param {any} module Module to load the contents.
* @param {number} [courseId] The course ID. Recommended to speed up the process and minimize data usage.
* @param {number} [sectionId] The section ID.
* @param {boolean} [preferCache] True if shouldn't call WS if data is cached, false otherwise.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<void>} Promise resolved when loaded.
*/
loadModuleContents(module: any, courseId?: number, sectionId?: number, preferCache?: boolean, ignoreCache?: boolean,
siteId?: string) : Promise<void> {
if (!ignoreCache && module.contents && module.contents.length) {
// Already loaded.
return Promise.resolve();
}
return this.getModule(module.id, courseId, sectionId, preferCache, ignoreCache, siteId).then((mod) => {
module.contents = mod.contents;
});
}
/**
* Report a course and section as being viewed.
*
* @param {number} courseId Course ID.
* @param {number} [sectionNumber] Section number.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<void>} Promise resolved when the WS call is successful.
*/
logView(courseId: number, sectionNumber?: number, siteId?: string) : Promise<void> {
let params: any = {
courseid: courseId
};
if (typeof sectionNumber != 'undefined') {
params.sectionnumber = sectionNumber;
}
return this.sitesProvider.getSite(siteId).then((site) => {
return site.write('core_course_view_course', params).then((response) => {
if (!response.status) {
return Promise.reject(null);
}
})
});
}
/**
* Change the course status, setting it to the previous status.
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<string>} Promise resolved when the status is changed. Resolve param: new status.
*/
setCoursePreviousStatus(courseId: number, siteId?: string) : Promise<string> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
this.logger.debug(`Set previous status for course ${courseId} in site ${siteId}`);
return this.sitesProvider.getSite(siteId).then((site) => {
let db = site.getDb(),
newData: any = {};
// Get current stored data.
return this.getCourseStatusData(courseId, siteId).then((entry) => {
this.logger.debug(`Set previous status '${entry.status}' for course ${courseId}`);
newData.status = entry.previous || CoreConstants.NOT_DOWNLOADED;
newData.updated = Date.now();
if (entry.status == CoreConstants.DOWNLOADING) {
// Going back from downloading to previous status, restore previous download time.
newData.downloadTime = entry.previousDownloadTime;
}
return db.updateRecords(this.COURSE_STATUS_TABLE, newData, {id: courseId}).then(() => {
// Success updating, trigger event.
this.triggerCourseStatusChanged(courseId, newData.status, siteId);
return newData.status;
});
});
});
}
/**
* Store course status.
*
* @param {number} courseId Course ID.
* @param {string} status New course status.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<void>} Promise resolved when the status is stored.
*/
setCourseStatus(courseId: number, status: string, siteId?: string) : Promise<void> {
siteId = siteId || this.sitesProvider.getCurrentSiteId()
this.logger.debug(`Set status '${status}' for course ${courseId} in site ${siteId}`);
return this.sitesProvider.getSite(siteId).then((site) => {
let downloadTime,
previousDownloadTime;
if (status == CoreConstants.DOWNLOADING) {
// Set download time if course is now downloading.
downloadTime = this.timeUtils.timestamp();
}
// Search current status to set it as previous status.
return this.getCourseStatusData(courseId, siteId).then((entry) => {
if (typeof downloadTime == 'undefined') {
// Keep previous download time.
downloadTime = entry.downloadTime;
previousDownloadTime = entry.previousDownloadTime;
} else {
// downloadTime will be updated, store current time as previous.
previousDownloadTime = entry.downloadTime;
}
return entry.status;
}).catch(() => {
// No previous status.
}).then((previousStatus) => {
if (previousStatus != status) {
// Status has changed, update it.
let data = {
id: courseId,
status: status,
previous: previousStatus,
updated: new Date().getTime(),
downloadTime: downloadTime,
previousDownloadTime: previousDownloadTime
};
return site.getDb().insertOrUpdateRecord(this.COURSE_STATUS_TABLE, data, {id: courseId});
}
}).then(() => {
// Success inserting, trigger event.
this.triggerCourseStatusChanged(courseId, status, siteId);
});
});
}
/**
* Translate a module name to current language.
*
* @param {string} moduleName The module name.
* @return {string} Translated name.
*/
translateModuleName(moduleName: string) : string {
if (this.CORE_MODULES.indexOf(moduleName) < 0) {
moduleName = 'external-tool';
}
const langKey = 'core.mod_' + moduleName,
translated = this.translate.instant(langKey);
return translated !== langKey ? translated : moduleName;
}
/**
* Trigger COURSE_STATUS_CHANGED with the right data.
*
* @param {number} courseId Course ID.
* @param {string} status New course status.
* @param {string} [siteId] Site ID. If not defined, current site.
*/
protected triggerCourseStatusChanged(courseId: number, status: string, siteId?: string) : void {
this.eventsProvider.trigger(CoreEventsProvider.COURSE_STATUS_CHANGED, {
courseId: courseId,
status: status
}, siteId);
}
}

View File

@ -0,0 +1,128 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreCoursesProvider } from '../../courses/providers/courses';
import { CoreCourseFormatHandler } from './format-delegate';
import { CoreCourseProvider } from './course';
/**
* Default handler used when the course format doesn't have a specific implementation.
*/
@Injectable()
export class CoreCourseFormatDefaultHandler implements CoreCourseFormatHandler {
name = 'default';
constructor(private coursesProvider: CoreCoursesProvider) {}
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled() : boolean|Promise<boolean> {
return true;
}
/**
* Get the title to use in course page.
*
* @param {any} course The course.
* @return {string} Title.
*/
getCourseTitle?(course: any) : string {
return course.fullname || '';
}
/**
* Whether it allows seeing all sections at the same time. Defaults to true.
*
* @param {any} course The course to check.
* @type {boolean} Whether it can view all sections.
*/
canViewAllSections(course: any) : boolean {
return true;
}
/**
* Whether the default section selector should be displayed. Defaults to true.
*
* @param {any} course The course to check.
* @type {boolean} Whether the default section selector should be displayed.
*/
displaySectionSelector(course: any) : boolean {
return true;
}
/**
* Given a list of sections, get the "current" section that should be displayed first.
*
* @param {any} course The course to get the title.
* @param {any[]} sections List of sections.
* @return {any|Promise<any>} Current section (or promise resolved with current section).
*/
getCurrentSection(course: any, sections: any[]) : any|Promise<any> {
// We need the "marker" to determine the current section.
return this.coursesProvider.getCoursesByField('id', course.id).catch(() => {
// Ignore errors.
}).then((courses) => {
if (courses && courses[0]) {
// Find the marked section.
let course = courses[0];
for (let i = 0; i < sections.length; i++) {
let section = sections[i];
if (section.section == course.marker) {
return section;
}
}
}
// Marked section not found or we couldn't retrieve the marker. Return the first section.
for (let i = 0; i < sections.length; i++) {
let section = sections[i];
if (section.id != CoreCourseProvider.ALL_SECTIONS_ID) {
return section;
}
}
return Promise.reject(null);
});
}
/**
* Invalidate the data required to load the course format.
*
* @param {any} course The course to get the title.
* @param {any[]} sections List of sections.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateData(course: any, sections: any[]) : Promise<any> {
return this.coursesProvider.invalidateCoursesByField('id', course.id);
}
/**
* Open the page to display a course. If not defined, the page CoreCourseSectionPage will be opened.
* Implement it only if you want to create your own page to display the course. In general it's better to use the method
* getCourseFormatComponent because it will display the course handlers at the top.
* Your page should include the course handlers using CoreCoursesDelegate.
*
* @param {NavController} navCtrl The NavController instance to use.
* @param {any} course The course to open. It should contain a "format" attribute.
* @return {Promise<any>} Promise resolved when done.
*/
openCourse(navCtrl: NavController, course: any) : Promise<any> {
return navCtrl.push('CoreCourseSectionPage', {course: course});
}
}

View File

@ -0,0 +1,391 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreEventsProvider } from '../../../providers/events';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSitesProvider } from '../../../providers/sites';
import { CoreCourseProvider } from './course';
import { CoreCourseFormatDefaultHandler } from './default-format';
/**
* Interface that all course format handlers must implement.
*/
export interface CoreCourseFormatHandler {
/**
* Name of the format. It should match the "format" returned in core_course_get_courses.
* @type {string}
*/
name: string;
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled(): boolean|Promise<boolean>;
/**
* Get the title to use in course page. If not defined, course fullname.
* This function will be called without sections first, and then call it again when the sections are retrieved.
*
* @param {any} course The course.
* @param {any[]} [sections] List of sections.
* @return {string} Title.
*/
getCourseTitle?(course: any, sections?: any[]) : string;
/**
* Whether it allows seeing all sections at the same time. Defaults to true.
*
* @param {any} course The course to check.
* @type {boolean} Whether it can view all sections.
*/
canViewAllSections?(course: any) : boolean;
/**
* Whether the default section selector should be displayed. Defaults to true.
*
* @param {any} course The course to check.
* @type {boolean} Whether the default section selector should be displayed.
*/
displaySectionSelector?(course: any) : boolean;
/**
* Given a list of sections, get the "current" section that should be displayed first. Defaults to first section.
*
* @param {any} course The course to get the title.
* @param {any[]} sections List of sections.
* @return {any|Promise<any>} Current section (or promise resolved with current section). If a promise is returned, it should
* never fail.
*/
getCurrentSection?(course: any, sections: any[]) : any|Promise<any>;
/**
* Open the page to display a course. If not defined, the page CoreCourseSectionPage will be opened.
* Implement it only if you want to create your own page to display the course. In general it's better to use the method
* getCourseFormatComponent because it will display the course handlers at the top.
* Your page should include the course handlers using CoreCoursesDelegate.
*
* @param {NavController} navCtrl The NavController instance to use.
* @param {any} course The course to open. It should contain a "format" attribute.
* @return {Promise<any>} Promise resolved when done.
*/
openCourse?(navCtrl: NavController, course: any) : Promise<any>;
/**
* Return the Component to use to display the course format instead of using the default one.
* Use it if you want to display a format completely different from the default one.
* If you want to customize the default format there are several methods to customize parts of it.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getCourseFormatComponent?(course: any) : any;
/**
* Return the Component to use to display the course summary inside the default course format.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getCourseSummaryComponent?(course: any): any;
/**
* Return the Component to use to display the section selector inside the default course format.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getSectionSelectorComponent?(course: any): any;
/**
* Return the Component to use to display a single section. This component will only be used if the user is viewing a
* single section. If all the sections are displayed at once then it won't be used.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getSingleSectionComponent?(course: any): any;
/**
* Return the Component to use to display all sections in a course.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getAllSectionsComponent?(course: any): any;
/**
* Invalidate the data required to load the course format.
*
* @param {any} course The course to get the title.
* @param {any[]} sections List of sections.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateData?(course: any, sections: any[]) : Promise<any>;
};
/**
* Service to interact with course formats. Provides the functions to register and interact with the addons.
*/
@Injectable()
export class CoreCourseFormatDelegate {
protected logger;
protected handlers: {[s: string]: CoreCourseFormatHandler} = {}; // All registered handlers.
protected enabledHandlers: {[s: string]: CoreCourseFormatHandler} = {}; // Handlers enabled for the current site.
protected lastUpdateHandlersStart: number;
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, eventsProvider: CoreEventsProvider,
private defaultHandler: CoreCourseFormatDefaultHandler) {
this.logger = logger.getInstance('CoreCoursesCourseFormatDelegate');
eventsProvider.on(CoreEventsProvider.LOGIN, this.updateHandlers.bind(this));
eventsProvider.on(CoreEventsProvider.SITE_UPDATED, this.updateHandlers.bind(this));
eventsProvider.on(CoreEventsProvider.REMOTE_ADDONS_LOADED, this.updateHandlers.bind(this));
}
/**
* Whether it allows seeing all sections at the same time. Defaults to true.
*
* @param {any} course The course to check.
* @return {boolean} Whether it allows seeing all sections at the same time.
*/
canViewAllSections(course: any) : boolean {
return this.executeFunction(course.format, 'canViewAllSections', [course]);
}
/**
* Whether the default section selector should be displayed. Defaults to true.
*
* @param {any} course The course to check.
* @return {boolean} Whether the section selector should be displayed.
*/
displaySectionSelector(course: any) : boolean {
return this.executeFunction(course.format, 'displaySectionSelector', [course]);
}
/**
* Execute a certain function in a course format handler.
* If the handler isn't found or function isn't defined, call the same function in the default handler.
*
* @param {string} format The format name.
* @param {string} fnName Name of the function to execute.
* @param {any[]} params Parameters to pass to the function.
* @return {any} Function returned value or default value.
*/
protected executeFunction(format: string, fnName: string, params?: any[]) : any {
let handler = this.enabledHandlers[format];
if (handler && handler[fnName]) {
return handler[fnName].apply(handler, params);
} else if (this.defaultHandler[fnName]) {
return this.defaultHandler[fnName].apply(this.defaultHandler, params);
}
}
/**
* Get the component to use to display all sections in a course.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getAllSectionsComponent(course: any) : any {
return this.executeFunction(course.format, 'getAllSectionsComponent', [course]);
}
/**
* Get the component to use to display a course format.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getCourseFormatComponent(course: any) : any {
return this.executeFunction(course.format, 'getCourseFormatComponent', [course]);
}
/**
* Get the component to use to display the course summary in the default course format.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getCourseSummaryComponent(course: any) : any {
return this.executeFunction(course.format, 'getCourseSummaryComponent', [course]);
}
/**
* Given a course, return the title to use in the course page.
*
* @param {any} course The course to get the title.
* @param {any[]} [sections] List of sections.
* @return {string} Course title.
*/
getCourseTitle(course: any, sections?: any[]) : string {
return this.executeFunction(course.format, 'getCourseTitle', [course, sections]);
}
/**
* Given a course and a list of sections, return the current section that should be displayed first.
*
* @param {any} course The course to get the title.
* @param {any[]} sections List of sections.
* @return {Promise<any>} Promise resolved with current section.
*/
getCurrentSection(course: any, sections: any[]) : Promise<any> {
// Convert the result to a Promise if it isn't.
return Promise.resolve(this.executeFunction(course.format, 'getCurrentSection', [course, sections])).catch(() => {
// This function should never fail. Just return the first section.
if (sections[0].id != CoreCourseProvider.ALL_SECTIONS_ID) {
return sections[0];
}
return sections[1];
});
}
/**
* Get the component to use to display the section selector inside the default course format.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getSectionSelectorComponent(course: any) : any {
return this.executeFunction(course.format, 'getSectionSelectorComponent', [course]);
}
/**
* Get the component to use to display a single section. This component will only be used if the user is viewing
* a single section. If all the sections are displayed at once then it won't be used.
*
* @param {any} course The course to render.
* @return {any} The component to use, undefined if not found.
*/
getSingleSectionComponent(course: any) : any {
return this.executeFunction(course.format, 'getSingleSectionComponent', [course]);
}
/**
* Invalidate the data required to load the course format.
*
* @param {any} course The course to get the title.
* @param {any[]} sections List of sections.
* @return {Promise<any>} Promise resolved when the data is invalidated.
*/
invalidateData(course: any, sections: any[]) : Promise<any> {
return this.executeFunction(course.format, 'invalidateData', [course, sections]);
}
/**
* Check if a time belongs to the last update handlers call.
* This is to handle the cases where updateHandlers don't finish in the same order as they're called.
*
* @param {number} time Time to check.
* @return {boolean} Whether it's the last call.
*/
isLastUpdateCall(time: number) : boolean {
if (!this.lastUpdateHandlersStart) {
return true;
}
return time == this.lastUpdateHandlersStart;
}
/**
* Open a course.
*
* @param {NavController} navCtrl The NavController instance to use.
* @param {any} course The course to open. It should contain a "format" attribute.
* @return {Promise<any>} Promise resolved when done.
*/
openCourse(navCtrl: NavController, course: any) : Promise<any> {
if (this.enabledHandlers[course.format] && this.enabledHandlers[course.format].openCourse) {
return this.enabledHandlers[course.format].openCourse(navCtrl, course);
}
return navCtrl.push('CoreCourseSectionPage', {course: course});
}
/**
* Register a handler.
*
* @param {CoreCourseFormatHandler} handler The handler to register.
* @return {boolean} True if registered successfully, false otherwise.
*/
registerHandler(handler: CoreCourseFormatHandler) : boolean {
if (typeof this.handlers[handler.name] !== 'undefined') {
this.logger.log(`Addon '${handler.name}' already registered`);
return false;
}
this.logger.log(`Registered addon '${handler.name}'`);
this.handlers[handler.name] = handler;
return true;
}
/**
* Update the handler for the current site.
*
* @param {CoreCourseFormatHandler} handler The handler to check.
* @param {number} time Time this update process started.
* @return {Promise<void>} Resolved when done.
*/
protected updateHandler(handler: CoreCourseFormatHandler, time: number) : Promise<void> {
let promise,
siteId = this.sitesProvider.getCurrentSiteId(),
currentSite = this.sitesProvider.getCurrentSite();
if (!this.sitesProvider.isLoggedIn()) {
promise = Promise.reject(null);
} else if (currentSite.isFeatureDisabled('CoreCourseFormatHandler_' + handler.name)) {
promise = Promise.resolve(false);
} else {
promise = Promise.resolve(handler.isEnabled());
}
// Checks if the handler is enabled.
return promise.catch(() => {
return false;
}).then((enabled: boolean) => {
// Verify that this call is the last one that was started.
// Check that site hasn't changed since the check started.
if (this.isLastUpdateCall(time) && this.sitesProvider.getCurrentSiteId() === siteId) {
if (enabled) {
this.enabledHandlers[handler.name] = handler;
} else {
delete this.enabledHandlers[handler.name];
}
}
});
}
/**
* Update the handlers for the current site.
*
* @return {Promise<any>} Resolved when done.
*/
protected updateHandlers() : Promise<any> {
let promises = [],
now = Date.now();
this.logger.debug('Updating handlers for current site.');
this.lastUpdateHandlersStart = now;
// Loop over all the handlers.
for (let name in this.handlers) {
promises.push(this.updateHandler(this.handlers[name], now));
}
return Promise.all(promises).catch(() => {
// Never reject.
});
}
}

View File

@ -0,0 +1,780 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { CoreFilepoolProvider } from '../../../providers/filepool';
import { CoreSitesProvider } from '../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../providers/utils/dom';
import { CoreTextUtilsProvider } from '../../../providers/utils/text';
import { CoreTimeUtilsProvider } from '../../../providers/utils/time';
import { CoreUtilsProvider } from '../../../providers/utils/utils';
import { CoreCoursesDelegate, CoreCoursesHandlerToDisplay } from '../../courses/providers/delegate';
import { CoreCourseProvider } from './course';
import { CoreCourseModuleDelegate } from './module-delegate';
import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchHandler } from './module-prefetch-delegate';
import { CoreConstants } from '../../constants';
import * as moment from 'moment';
/**
* Prefetch info of a module.
*/
export type CoreCourseModulePrefetchInfo = {
/**
* Downloaded size.
* @type {number}
*/
size?: number;
/**
* Downloadable size in a readable format.
* @type {string}
*/
sizeReadable?: string;
/**
* Module status.
* @type {string}
*/
status?: string;
/**
* Icon's name of the module status.
* @type {string}
*/
statusIcon?: string;
/**
* Time when the module was last downloaded.
* @type {number}
*/
downloadTime?: number;
/**
* Download time in a readable format.
* @type {string}
*/
downloadTimeReadable?: string;
};
/**
* Progress of downloading a list of courses.
*/
export type CoreCourseCoursesProgress = {
/**
* Number of courses downloaded so far.
* @type {number}
*/
count: number;
/**
* Toal of courses to download.
* @type {number}
*/
total: number;
/**
* Whether the download has been successful so far.
* @type {boolean}
*/
success: boolean;
/**
* Last downloaded course.
* @type {number}
*/
courseId?: number;
};
/**
* Helper to gather some common course functions.
*/
@Injectable()
export class CoreCourseHelperProvider {
protected courseDwnPromises: {[s: string]: {[id: number]: Promise<any>}} = {};
constructor(private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider,
private moduleDelegate: CoreCourseModuleDelegate, private prefetchDelegate: CoreCourseModulePrefetchDelegate,
private filepoolProvider: CoreFilepoolProvider, private sitesProvider: CoreSitesProvider,
private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider,
private utils: CoreUtilsProvider, private translate: TranslateService, private coursesDelegate: CoreCoursesDelegate) {}
/**
* This function treats every module on the sections provided to load the handler data, treat completion
* and navigate to a module page if required. It also returns if sections has content.
*
* @param {any[]} sections List of sections to treat modules.
* @param {number} courseId Course ID of the modules.
* @param {number} [moduleId] Module to navigate to if needed.
* @param {any[]} [completionStatus] List of completion status.
* @return {boolean} Whether the sections have content.
*/
addHandlerDataForModules(sections: any[], courseId: number, moduleId?: number, completionStatus?: any) {
let hasContent = false;
sections.forEach((section) => {
if (!section || !this.sectionHasContent(section) || !section.modules) {
return;
}
hasContent = true;
section.modules.forEach((module) => {
module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, section.id);
if (completionStatus && typeof completionStatus[module.id] != 'undefined') {
// Check if activity has completions and if it's marked.
module.completionstatus = completionStatus[module.id];
module.completionstatus.courseId = courseId;
}
if (module.id == moduleId) {
// This is the module we're looking for. Open it.
module.handlerData.action(new Event('click'), module, courseId);
}
});
});
return hasContent;
}
/**
* Calculate the status of a section.
*
* @param {any} section Section to calculate its status. It can't be "All sections".
* @param {number} courseId Course ID the section belongs to.
* @param {boolean} [refresh] True if it shouldn't use module status cache (slower).
* @return {Promise<any>} Promise resolved when the status is calculated.
*/
calculateSectionStatus(section: any, courseId: number, refresh?: boolean) : Promise<any> {
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID) {
return Promise.reject(null);
}
// Get the status of this section.
return this.prefetchDelegate.getModulesStatus(section.modules, courseId, section.id, refresh).then((result) => {
// Check if it's being downloaded.
const downloadId = this.getSectionDownloadId(section);
if (this.prefetchDelegate.isBeingDownloaded(downloadId)) {
result.status = CoreConstants.DOWNLOADING;
}
// Set this section data.
section.showDownload = result.status === CoreConstants.NOT_DOWNLOADED;
section.showRefresh = result.status === CoreConstants.OUTDATED;
if (result.status !== CoreConstants.DOWNLOADING || !this.prefetchDelegate.isBeingDownloaded(section.id)) {
section.isDownloading = false;
section.total = 0;
} else {
// Section is being downloaded.
section.isDownloading = true;
this.prefetchDelegate.setOnProgress(downloadId, (data) => {
section.count = data.count;
section.total = data.total;
});
}
return result;
});
}
/**
* Calculate the status of a list of sections, setting attributes to determine the icons/data to be shown.
*
* @param {any[]} sections Sections to calculate their status.
* @param {number} courseId Course ID the sections belong to.
* @param {boolean} [refresh] True if it shouldn't use module status cache (slower).
* @return {Promise<void>} Promise resolved when the states are calculated.
*/
calculateSectionsStatus(sections: any[], courseId: number, refresh?: boolean) : Promise<void> {
let allSectionsSection,
allSectionsStatus,
promises = [];
sections.forEach((section) => {
if (section.id === CoreCourseProvider.ALL_SECTIONS_ID) {
// "All sections" section status is calculated using the status of the rest of sections.
allSectionsSection = section;
section.isCalculating = true;
} else {
section.isCalculating = true;
promises.push(this.calculateSectionStatus(section, courseId, refresh).then((result) => {
// Calculate "All sections" status.
allSectionsStatus = this.filepoolProvider.determinePackagesStatus(allSectionsStatus, result.status);
}).finally(() => {
section.isCalculating = false;
}));
}
});
return Promise.all(promises).then(() => {
if (allSectionsSection) {
// Set "All sections" data.
allSectionsSection.showDownload = allSectionsStatus === CoreConstants.NOT_DOWNLOADED;
allSectionsSection.showRefresh = allSectionsStatus === CoreConstants.OUTDATED;
allSectionsSection.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
}
}).finally(() => {
if (allSectionsSection) {
allSectionsSection.isCalculating = false;
}
});
}
/**
* Show a confirm and prefetch a course. It will retrieve the sections and the course options if not provided.
* This function will set the icon to "spinner" when starting and it will also set it back to the initial icon if the
* user cancels. All the other updates of the icon should be made when CoreEventsProvider.COURSE_STATUS_CHANGED is received.
*
* @param {any} iconData An object where to store the course icon. It will be stored with the name "prefetchCourseIcon".
* @param {any} course Course to prefetch.
* @param {any[]} [sections] List of course sections.
* @param {CoreCoursesHandlerToDisplay[]} courseHandlers List of course handlers.
* @return {Promise<boolean>} Promise resolved with true when the download finishes, resolved with false if user doesn't
* confirm, rejected if an error occurs.
*/
confirmAndPrefetchCourse(iconData: any, course: any, sections?: any[], courseHandlers?: CoreCoursesHandlerToDisplay[])
: Promise<boolean> {
let initialIcon = iconData.prefetchCourseIcon,
promise,
siteId = this.sitesProvider.getCurrentSiteId();
iconData.prefetchCourseIcon = 'spinner';
// Get the sections first if needed.
if (sections) {
promise = Promise.resolve(sections);
} else {
promise = this.courseProvider.getSections(course.id, false, true);
}
return promise.then((sections) => {
// Confirm the download.
return this.confirmDownloadSizeSection(course.id, undefined, sections, true).then(() => {
// User confirmed, get the course handlers if needed.
if (courseHandlers) {
promise = Promise.resolve(courseHandlers);
} else {
promise = this.coursesDelegate.getHandlersToDisplay(course);
}
return promise.then((handlers: CoreCoursesHandlerToDisplay[]) => {
// Now we have all the data, download the course.
return this.prefetchCourse(course, sections, handlers, siteId);
}).then(() => {
// Download successful.
return true;
});
}, (error) : any => {
// User cancelled or there was an error calculating the size.
iconData.prefetchCourseIcon = initialIcon;
if (error) {
return Promise.reject(error);
}
return false;
});
});
};
/**
* Confirm and prefetches a list of courses.
*
* @param {any[]} courses List of courses to download.
* @param {Function} [onProgress] Function to call everytime a course is downloaded.
* @return {Promise<boolean>} Resolved with true when downloaded, resolved with false if user cancels, rejected if error.
*/
confirmAndPrefetchCourses(courses: any[], onProgress?: (data: CoreCourseCoursesProgress) => void) : Promise<boolean> {
const siteId = this.sitesProvider.getCurrentSiteId();
// Confirm the download without checking size because it could take a while.
return this.domUtils.showConfirm(this.translate.instant('core.areyousure')).then(() => {
let promises = [],
total = courses.length,
count = 0;
courses.forEach((course) => {
let subPromises = [],
sections,
handlers,
success = true;
// Get the sections and the handlers.
subPromises.push(this.courseProvider.getSections(course.id, false, true).then((courseSections) => {
sections = courseSections;
}));
subPromises.push(this.coursesDelegate.getHandlersToDisplay(course).then((cHandlers) => {
handlers = cHandlers;
}));
promises.push(Promise.all(subPromises).then(() => {
return this.prefetchCourse(course, sections, handlers, siteId);
}).catch((error) => {
success = false;
return Promise.reject(error);
}).finally(() => {
// Course downloaded or failed, notify the progress.
count++;
if (onProgress) {
onProgress({count: count, total: total, courseId: course.id, success: success});
}
}));
});
if (onProgress) {
// Notify the start of the download.
onProgress({count: 0, total: total, success: true});
}
return this.utils.allPromises(promises).then(() => {
return true;
});
}, () => {
// User cancelled.
return false;
});
};
/**
* Show confirmation dialog and then remove a module files.
*
* @param {any} module Module to remove the files.
* @param {number} courseId Course ID the module belongs to.
* @return {Promise<any>} Promise resolved when done.
*/
confirmAndRemoveFiles(module: any, courseId: number) : Promise<any> {
return this.domUtils.showConfirm(this.translate.instant('course.confirmdeletemodulefiles')).then(() => {
return this.prefetchDelegate.removeModuleFiles(module, courseId);
});
}
/**
* Calculate the size to download a section and show a confirm modal if needed.
*
* @param {number} courseId Course ID the section belongs to.
* @param {any} [section] Section. If not provided, all sections.
* @param {any[]} [sections] List of sections. Used when downloading all the sections.
* @param {boolean} [alwaysConfirm] True to show a confirm even if the size isn't high, false otherwise.
* @return {Promise<any>} Promise resolved if the user confirms or there's no need to confirm.
*/
confirmDownloadSizeSection(courseId: number, section?: any, sections?: any[], alwaysConfirm?: boolean) : Promise<any> {
let sizePromise;
// Calculate the size of the download.
if (section && section.id != CoreCourseProvider.ALL_SECTIONS_ID) {
sizePromise = this.prefetchDelegate.getDownloadSize(section.modules, courseId);
} else {
let promises = [],
results = {
size: 0,
total: true
};
sections.forEach((s) => {
if (s.id != CoreCourseProvider.ALL_SECTIONS_ID) {
promises.push(this.prefetchDelegate.getDownloadSize(s.modules, courseId).then((sectionSize) => {
results.total = results.total && sectionSize.total;
results.size += sectionSize.size;
}));
}
});
sizePromise = Promise.all(promises).then(() => {
return results;
});
}
return sizePromise.then((size) => {
// Show confirm modal if needed.
return this.domUtils.confirmDownloadSize(size, undefined, undefined, undefined, undefined, alwaysConfirm);
});
}
/**
* Determine the status of a list of courses.
*
* @param {any[]} courses Courses
* @return {Promise<string>} Promise resolved with the status.
*/
determineCoursesStatus(courses: any[]) : Promise<string> {
// Get the status of each course.
const promises = [],
siteId = this.sitesProvider.getCurrentSiteId();
courses.forEach((course) => {
promises.push(this.courseProvider.getCourseStatus(course.id, siteId));
});
return Promise.all(promises).then((statuses) => {
// Now determine the status of the whole list.
let status = statuses[0];
for (let i = 1; i < statuses.length; i++) {
status = this.filepoolProvider.determinePackagesStatus(status, statuses[i]);
}
return status;
});
}
/**
* Get a course download promise (if any).
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Download promise, undefined if not found.
*/
getCourseDownloadPromise(courseId: number, siteId?: string) : Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
return this.courseDwnPromises[siteId] && this.courseDwnPromises[siteId][courseId];
}
/**
* Get a course status icon.
*
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<string>} Promise resolved with the icon name.
*/
getCourseStatusIcon(courseId: number, siteId?: string) : Promise<string> {
return this.courseProvider.getCourseStatus(courseId, siteId).then((status) => {
return this.getCourseStatusIconFromStatus(status);
});
}
/**
* Get a course status icon from status.
*
* @module mm.core.course
* @ngdoc method
* @name $mmCourseHelper#getCourseStatusIconFromStatus
* @param {String} status Course status.
* @return {String} Icon name.
*/
getCourseStatusIconFromStatus(status: string) : string {
if (status == CoreConstants.DOWNLOADED) {
// Always show refresh icon, we cannot knew if there's anything new in course options.
return 'refresh';
} else if (status == CoreConstants.DOWNLOADING) {
return 'spinner';
} else {
return 'cloud-download';
}
}
/**
* Get the course ID from a module instance ID, showing an error message if it can't be retrieved.
*
* @param {number} id Instance ID.
* @param {string} module Name of the module. E.g. 'glossary'.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<number>} Promise resolved with the module's course ID.
*/
getModuleCourseIdByInstance(id: number, module: any, siteId?: string) : Promise<number> {
return this.courseProvider.getModuleBasicInfoByInstance(id, module, siteId).then((cm) => {
return cm.course;
}).catch((error) => {
this.domUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
return Promise.reject(null);
});
}
/**
* Get prefetch info for a module.
*
* @param {any} module Module to get the info from.
* @param {number} courseId Course ID the section belongs to.
* @param {boolean} [invalidateCache] Invalidates the cache first.
* @param {string} [component] Component of the module.
* @return {Promise<CoreCourseModulePrefetchInfo>} Promise resolved with the info.
*/
getModulePrefetchInfo(module: any, courseId: number, invalidateCache?: boolean, component?: string)
: Promise<CoreCourseModulePrefetchInfo> {
let moduleInfo: CoreCourseModulePrefetchInfo = {},
siteId = this.sitesProvider.getCurrentSiteId(),
promises = [];
if (invalidateCache) {
this.prefetchDelegate.invalidateModuleStatusCache(module);
}
promises.push(this.prefetchDelegate.getModuleDownloadedSize(module, courseId).then((moduleSize) => {
moduleInfo.size = moduleSize;
moduleInfo.sizeReadable = this.textUtils.bytesToSize(moduleSize, 2);
}));
// @todo: Decide what to display instead of timemodified. Last check_updates?
// promises.push(this.prefetchDelegate.getModuleTimemodified(module, courseId).then(function(moduleModified) {
// moduleInfo.timemodified = moduleModified;
// if (moduleModified > 0) {
// var now = $mmUtil.timestamp();
// if (now - moduleModified < 7 * 86400) {
// moduleInfo.timemodifiedReadable = moment(moduleModified * 1000).fromNow();
// } else {
// moduleInfo.timemodifiedReadable = moment(moduleModified * 1000).calendar();
// }
// } else {
// moduleInfo.timemodifiedReadable = "";
// }
// }));
promises.push(this.prefetchDelegate.getModuleStatus(module, courseId).then((moduleStatus) => {
moduleInfo.status = moduleStatus;
switch (moduleStatus) {
case CoreConstants.NOT_DOWNLOADED:
moduleInfo.statusIcon = 'cloud-download';
break;
case CoreConstants.DOWNLOADING:
moduleInfo.statusIcon = 'spinner';
break;
case CoreConstants.OUTDATED:
moduleInfo.statusIcon = 'ion-android-refresh';
break;
default:
moduleInfo.statusIcon = '';
break;
}
}));
// Get the time it was downloaded (if it was downloaded).
promises.push(this.filepoolProvider.getPackageData(siteId, component, module.id).then((data) => {
if (data && data.downloadTime && (data.status == CoreConstants.OUTDATED || data.status == CoreConstants.DOWNLOADED)) {
const now = this.timeUtils.timestamp();
moduleInfo.downloadTime = data.downloadTime;
if (now - data.downloadTime < 7 * 86400) {
moduleInfo.downloadTimeReadable = moment(data.downloadTime * 1000).fromNow();
} else {
moduleInfo.downloadTimeReadable = moment(data.downloadTime * 1000).calendar();
}
}
}).catch(() => {
// Not downloaded.
moduleInfo.downloadTime = 0;
}));
return Promise.all(promises).then(() => {
return moduleInfo;
});
}
/**
* Get the download ID of a section. It's used to interact with CoreCourseModulePrefetchDelegate.
*
* @param {any} section Section.
* @return {string} Section download ID.
*/
getSectionDownloadId(section: any) : string {
return 'Section-' + section.id;
}
/**
* Prefetch all the activities in a course and also the course addons.
*
* @param {any} course The course to prefetch.
* @param {any[]} sections List of course sections.
* @param {CoreCoursesHandlerToDisplay[]} courseHandlers List of course handlers.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise} Promise resolved when the download finishes.
*/
prefetchCourse(course: any, sections: any[], courseHandlers: CoreCoursesHandlerToDisplay[], siteId?: string) : Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
if (this.courseDwnPromises[siteId] && this.courseDwnPromises[siteId][course.id]) {
// There's already a download ongoing for this course, return the promise.
return this.courseDwnPromises[siteId][course.id];
} else if (!this.courseDwnPromises[siteId]) {
this.courseDwnPromises[siteId] = {};
}
// First of all, mark the course as being downloaded.
this.courseDwnPromises[siteId][course.id] = this.courseProvider.setCourseStatus(course.id, CoreConstants.DOWNLOADING,
siteId).then(() => {
let promises = [],
allSectionsSection = sections[0];
// Prefetch all the sections. If the first section is "All sections", use it. Otherwise, use a fake "All sections".
if (sections[0].id != CoreCourseProvider.ALL_SECTIONS_ID) {
allSectionsSection = {id: CoreCourseProvider.ALL_SECTIONS_ID};
}
promises.push(this.prefetchSection(allSectionsSection, course.id, sections));
// Prefetch course options.
courseHandlers.forEach((handler) => {
if (handler.prefetch) {
promises.push(handler.prefetch(course));
}
});
return this.utils.allPromises(promises);
}).then(() => {
// Download success, mark the course as downloaded.
return this.courseProvider.setCourseStatus(course.id, CoreConstants.DOWNLOADED, siteId);
}).catch((error) => {
// Error, restore previous status.
return this.courseProvider.setCoursePreviousStatus(course.id, siteId).then(() => {
return Promise.reject(error);
});
}).finally(() => {
delete this.courseDwnPromises[siteId][course.id];
});
return this.courseDwnPromises[siteId][course.id];
}
/**
* Helper function to prefetch a module, showing a confirmation modal if the size is big
* and invalidating contents if refreshing.
*
* @param {handler} handler Prefetch handler to use. Must implement 'prefetch' and 'invalidateContent'.
* @param {any} module Module to download.
* @param {any} size Object containing size to download (in bytes) and a boolean to indicate if its totally calculated.
* @param {number} courseId Course ID of the module.
* @param {boolean} [refresh] True if refreshing, false otherwise.
* @return {Promise<any>} Promise resolved when downloaded.
*/
prefetchModule(handler: any, module: any, size: any, courseId: number, refresh?: boolean) : Promise<any> {
// Show confirmation if needed.
return this.domUtils.confirmDownloadSize(size).then(() => {
// Invalidate content if refreshing and download the data.
let promise = refresh ? handler.invalidateContent(module.id, courseId) : Promise.resolve();
return promise.catch(() => {
// Ignore errors.
}).then(() => {
return handler.prefetch(module, courseId, true);
});
});
}
/**
* Prefetch one section or all the sections.
* If the section is "All sections" it will prefetch all the sections.
*
* @param {any} section Section.
* @param {number} courseId Course ID the section belongs to.
* @param {any[]} [sections] List of sections. Used when downloading all the sections.
* @return {Promise<any>} Promise resolved when the prefetch is finished.
*/
prefetchSection(section: any, courseId: number, sections?: any[]) : Promise<any> {
if (section.id != CoreCourseProvider.ALL_SECTIONS_ID) {
// Download only this section.
return this.prefetchSingleSectionIfNeeded(section, courseId).then(() => {
// Calculate the status of the section that finished.
return this.calculateSectionStatus(section, courseId);
});
} else {
// Download all the sections except "All sections".
let promises = [],
allSectionsStatus;
section.isDownloading = true;
sections.forEach((section) => {
if (section.id != CoreCourseProvider.ALL_SECTIONS_ID) {
promises.push(this.prefetchSingleSectionIfNeeded(section, courseId).then(() => {
// Calculate the status of the section that finished.
return this.calculateSectionStatus(section, courseId).then((result) => {
// Calculate "All sections" status.
allSectionsStatus = this.filepoolProvider.determinePackagesStatus(allSectionsStatus, result.status);
});
}));
}
});
return this.utils.allPromises(promises).then(() => {
// Set "All sections" data.
section.showDownload = allSectionsStatus === CoreConstants.NOT_DOWNLOADED;
section.showRefresh = allSectionsStatus === CoreConstants.OUTDATED;
section.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
}).finally(() => {
section.isDownloading = false;
});
}
}
/**
* Prefetch a certain section if it needs to be prefetched.
* If the section is "All sections" it will be ignored.
*
* @param {any} section Section to prefetch.
* @param {number} courseId Course ID the section belongs to.
* @return {Promise<any>} Promise resolved when the section is prefetched.
*/
protected prefetchSingleSectionIfNeeded(section: any, courseId: number) : Promise<any> {
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID) {
return Promise.resolve();
}
section.isDownloading = true;
// Validate the section needs to be downloaded and calculate amount of modules that need to be downloaded.
return this.prefetchDelegate.getModulesStatus(section.modules, courseId, section.id).then((result) => {
if (result.status == CoreConstants.DOWNLOADED || result.status == CoreConstants.NOT_DOWNLOADABLE) {
// Section is downloaded or not downloadable, nothing to do.
return;
}
return this.prefetchSingleSection(section, result, courseId);
}, (error) => {
section.isDownloading = false;
return Promise.reject(error);
});
}
/**
* Start or restore the prefetch of a section.
* If the section is "All sections" it will be ignored.
*
* @param {any} section Section to download.
* @param {any} result Result of CoreCourseModulePrefetchDelegate.getModulesStatus for this section.
* @param {number} courseId Course ID the section belongs to.
* @return {Promise<any>} Promise resolved when the section has been prefetched.
*/
protected prefetchSingleSection(section: any, result: any, courseId: number) {
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID) {
return Promise.resolve();
}
if (section.total > 0) {
// Already being downloaded.
return Promise.resolve();
}
// We only download modules with status notdownloaded, downloading or outdated.
let modules = result[CoreConstants.OUTDATED].concat(result[CoreConstants.NOT_DOWNLOADED])
.concat(result[CoreConstants.DOWNLOADING]),
downloadId = this.getSectionDownloadId(section);
section.isDownloading = true;
// We prefetch all the modules to prevent incoeherences in the download count
// and also to download stale data that might not be marked as outdated.
return this.prefetchDelegate.prefetchModules(downloadId, modules, courseId, (data) => {
section.count = data.count;
section.total = data.total;
});
}
/**
* Check if a section has content.
*
* @param {any} section Section to check.
* @return {boolean} Whether the section has content.
*/
sectionHasContent(section: any) : boolean {
if (section.id == CoreCourseProvider.ALL_SECTIONS_ID || section.hiddenbynumsections) {
return false;
}
return (typeof section.availabilityinfo != 'undefined' && section.availabilityinfo != '') ||
section.summary != '' || (section.modules && section.modules.length > 0);
}
}

View File

@ -0,0 +1,361 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreEventsProvider } from '../../../providers/events';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSitesProvider } from '../../../providers/sites';
import { CoreCourseProvider } from './course';
import { CoreSite } from '../../../classes/site';
/**
* Interface that all course module handlers must implement.
*/
export interface CoreCourseModuleHandler {
/**
* A name to identify the addon.
* @type {string}
*/
name: string;
/**
* Name of the module. It should match the "modname" of the module returned in core_course_get_contents.
* @type {string}
*/
modname: string;
/**
* Whether or not the handler is enabled on a site level.
*
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
*/
isEnabled(): boolean|Promise<boolean>;
/**
* Get the data required to display the module in the course contents view.
*
* @param {any} module The module object.
* @param {number} courseId The course ID.
* @param {number} sectionId The section ID.
* @return {CoreCourseModuleHandlerData} Data to render the module.
*/
getData(module: any, courseId: number, sectionId: number) : CoreCourseModuleHandlerData;
/**
* Get the component to render the module. This is needed to support singleactivity course format.
*
* @param {any} course The course object.
* @param {any} module The module object.
* @return {any} The component to use, undefined if not found.
*/
getMainComponent(course: any, module: any) : any;
};
/**
* Data needed to render the module in course contents.
*/
export interface CoreCourseModuleHandlerData {
/**
* The title to display in the module.
* @type {string}
*/
title: string;
/**
* The image to use as icon (path to the image).
* @type {string}
*/
icon?: string;
/**
* The class to assign to the item.
* @type {string}
*/
class?: string;
/**
* The buttons to display in the module item.
* @type {CoreCourseModuleHandlerButton[]}
*/
buttons?: CoreCourseModuleHandlerButton[];
/**
* Whether to display a spinner in the module item.
* @type {boolean}
*/
spinner?: boolean;
/**
* Action to perform when the module is clicked.
*
* @param {Event} event The click event.
* @param {NavController} navCtrl NavController instance.
* @param {any} module The module object.
* @param {number} courseId The course ID.
*/
action?(event: Event, navCtrl: NavController, module: any, courseId: number) : void;
};
/**
* A button to display in a module item.
*/
export interface CoreCourseModuleHandlerButton {
/**
* The label to add to the button.
* @type {string}
*/
label: string;
/**
* The name of the button icon.
* @type {string}
*/
icon: string;
/**
* Whether the button should be hidden.
* @type {boolean}
*/
hidden?: boolean;
/**
* The name of the button icon to use in iOS instead of "icon".
* @type {string}
*/
iosIcon?: string;
/**
* The name of the button icon to use in MaterialDesign instead of "icon".
* @type {string}
*/
mdIcon?: string;
/**
* Action to perform when the button is clicked.
*
* @param {Event} event The click event.
* @param {NavController} navCtrl NavController instance.
* @param {any} module The module object.
* @param {number} courseId The course ID.
*/
action(event: Event, navCtrl: NavController, module: any, courseId: number) : void;
};
/**
* Delegate to register module handlers.
*/
@Injectable()
export class CoreCourseModuleDelegate {
protected logger;
protected handlers: {[s: string]: CoreCourseModuleHandler} = {}; // All registered handlers.
protected enabledHandlers: {[s: string]: CoreCourseModuleHandler} = {}; // Handlers enabled for the current site.
protected lastUpdateHandlersStart: number;
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, eventsProvider: CoreEventsProvider,
private courseProvider: CoreCourseProvider) {
this.logger = logger.getInstance('CoreCourseModuleDelegate');
eventsProvider.on(CoreEventsProvider.LOGIN, this.updateHandlers.bind(this));
eventsProvider.on(CoreEventsProvider.SITE_UPDATED, this.updateHandlers.bind(this));
eventsProvider.on(CoreEventsProvider.REMOTE_ADDONS_LOADED, this.updateHandlers.bind(this));
}
/**
* Get the component to render the module.
*
* @param {any} course The course object.
* @param {any} module The module object.
* @return {any} The component to use, undefined if not found.
*/
getMainComponent?(course: any, module: any) : any {
let handler = this.enabledHandlers[module.modname];
if (handler && handler.getMainComponent) {
let component = handler.getMainComponent(course, module);
if (component) {
return component;
}
}
}
/**
* Get the data required to display the module in the course contents view.
*
* @param {string} modname The name of the module type.
* @param {any} module The module object.
* @param {number} courseId The course ID.
* @param {number} sectionId The section ID.
* @return {CoreCourseModuleHandlerData} Data to render the module.
*/
getModuleDataFor(modname: string, module: any, courseId: number, sectionId: number) : CoreCourseModuleHandlerData {
if (typeof this.enabledHandlers[modname] != 'undefined') {
return this.enabledHandlers[modname].getData(module, courseId, sectionId);
}
// Return the default data.
let defaultData: CoreCourseModuleHandlerData = {
icon: this.courseProvider.getModuleIconSrc(module.modname),
title: module.name,
class: 'core-course-default-handler core-course-module-' + module.modname + '-handler',
action: (event: Event, navCtrl: NavController, module: any, courseId: number) => {
event.preventDefault();
event.stopPropagation();
navCtrl.push('CoreCourseUnsupportedModulePage', {module: module});
}
};
if (module.url) {
defaultData.buttons = [{
icon: 'open',
label: 'core.openinbrowser',
action: (e: Event) => {
e.preventDefault();
e.stopPropagation();
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(module.url);
}
}];
}
return defaultData;
};
/**
* Check if a module has a registered handler (not necessarily enabled).
*
* @param {string} modname The name of the module type.
* @return {boolean} If the controller is installed or not.
*/
hasHandler(modname: string) : boolean {
return typeof this.handlers[modname] !== 'undefined';
}
/**
* Check if a certain module type is disabled in a site.
*
* @param {string} modname The name of the module type.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<boolean>} Promise resolved with boolean: whether module is disabled.
*/
isModuleDisabled(modname: string, siteId?: string) : Promise<boolean> {
return this.sitesProvider.getSite(siteId).then((site) => {
return this.isModuleDisabledInSite(modname, site);
});
}
/**
* Check if a certain module type is disabled in a site.
*
* @param {string} modname The name of the module type.
* @param {CoreSite} [site] Site. If not defined, use current site.
* @return {boolean} Whether module is disabled.
*/
isModuleDisabledInSite(modname: string, site?: CoreSite) : boolean {
site = site || this.sitesProvider.getCurrentSite();
if (typeof this.handlers[modname] != 'undefined') {
return site.isFeatureDisabled('$mmCourseDelegate_' + this.handlers[modname].name);
}
return false;
}
/**
* Check if a time belongs to the last update handlers call.
* This is to handle the cases where updateHandlers don't finish in the same order as they're called.
*
* @param {number} time Time to check.
* @return {boolean} Whether it's the last call.
*/
isLastUpdateCall(time: number) : boolean {
if (!this.lastUpdateHandlersStart) {
return true;
}
return time == this.lastUpdateHandlersStart;
}
/**
* Register a handler.
*
* @param {CoreCourseModuleHandler} handler The handler to register.
* @return {boolean} True if registered successfully, false otherwise.
*/
registerHandler(handler: CoreCourseModuleHandler) : boolean {
if (typeof this.handlers[handler.modname] !== 'undefined') {
this.logger.log('There is an addon named \'' + this.handlers[handler.modname].name +
'\' already registered as handler for ' + handler.modname);
return false;
}
this.logger.log(`Registered addon '${handler.name}' for '${handler.modname}'`);
this.handlers[handler.modname] = handler;
return true;
}
/**
* Update the handler for the current site.
*
* @param {CoreCourseModuleHandler} handler The handler to check.
* @param {number} time Time this update process started.
* @return {Promise<void>} Resolved when done.
*/
protected updateHandler(handler: CoreCourseModuleHandler, time: number) : Promise<void> {
let promise,
siteId = this.sitesProvider.getCurrentSiteId(),
currentSite = this.sitesProvider.getCurrentSite();
if (!this.sitesProvider.isLoggedIn()) {
promise = Promise.reject(null);
} else if (currentSite.isFeatureDisabled('$mmCourseDelegate_' + handler.name)) {
promise = Promise.resolve(false);
} else {
promise = Promise.resolve(handler.isEnabled());
}
// Checks if the handler is enabled.
return promise.catch(() => {
return false;
}).then((enabled: boolean) => {
// Verify that this call is the last one that was started.
if (this.isLastUpdateCall(time) && this.sitesProvider.getCurrentSiteId() === siteId) {
if (enabled) {
this.enabledHandlers[handler.modname] = handler;
} else {
delete this.enabledHandlers[handler.modname];
}
}
});
}
/**
* Update the handlers for the current site.
*
* @return {Promise<any>} Resolved when done.
*/
protected updateHandlers() : Promise<any> {
let promises = [],
now = Date.now();
this.logger.debug('Updating handlers for current site.');
this.lastUpdateHandlersStart = now;
// Loop over all the handlers.
for (let name in this.handlers) {
promises.push(this.updateHandler(this.handlers[name], now));
}
return Promise.all(promises).catch(() => {
// Never reject.
});
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,18 @@
<ion-card>
<a ion-item text-wrap detail-none (click)="openCourse(course)" [title]="course.fullname">
<h2 float-start><core-format-text [text]="course.fullname"></core-format-text></h2>
<!-- Download course. -->
<!--<button [hidden]="!downloadButton.isDownload" ion-button icon-only clear color="dark" float-end>
<ion-icon name="cloud-download"></ion-icon>
</button>-->
<!-- Download course spinner. -->
<!-- <ion-spinner *ngIf="prefetchCourseIcon == 'spinner'" class="core-course-download-spinner"></ion-spinner> -->
</a>
<ion-item tappable text-wrap detail-none (click)="openCourse(course)" [title]="course.fullname">
<div class="core-course-link">
<h2><core-format-text [text]="course.fullname"></core-format-text></h2>
<div class="core-button-spinner">
<!-- Download course. -->
<button *ngIf="prefetchCourseData.prefetchCourseIcon != 'spinner'" ion-button icon-only clear color="dark" (click)="prefetchCourse($event)">
<ion-icon [name]="prefetchCourseData.prefetchCourseIcon"></ion-icon>
</button>
<!-- Download course spinner. -->
<ion-spinner *ngIf="prefetchCourseData.prefetchCourseIcon == 'spinner'"></ion-spinner>
</div>
</div>
</ion-item>
<ion-item text-wrap *ngIf="course.summary && course.summary.length">
<p>
<summary>

View File

@ -1,12 +1,34 @@
core-courses-course-progress.core-courseoverview {
@media (max-width: 576px) {
core-courses-course-progress {
&.core-courseoverview {
@media (max-width: 576px) {
ion-card.card {
margin: 0;
border-radius: 0;
box-shadow: none;
border-bottom: 1px solid $list-border-color;
width: 100%;
height: 100% !important;
}
}
ion-card.card {
margin: 0;
border-radius: 0;
box-shadow: none;
border-bottom: 1px solid $list-border-color;
width: 100%;
height: 100% !important;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
button {
z-index: 1;
}
.core-course-link {
display: flex;
align-items: center;
justify-content: space-between;
h2 {
flex-grow: 1;
}
}
}

View File

@ -12,9 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { NavController } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreEventsProvider } from '../../../../providers/events';
import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreCourseFormatDelegate } from '../../../course/providers/format-delegate';
import { CoreCourseProvider } from '../../../course/providers/course';
import { CoreCourseHelperProvider } from '../../../course/providers/helper';
/**
* This component is meant to display a course for a list of courses with progress.
@ -28,38 +34,85 @@ import { TranslateService } from '@ngx-translate/core';
selector: 'core-courses-course-progress',
templateUrl: 'course-progress.html'
})
export class CoreCoursesCourseProgressComponent implements OnInit {
export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
@Input() course: any; // The course to render.
isDownloading: boolean;
protected obsStatus;
protected downloadText;
protected downloadingText;
protected downloadButton = {
isDownload: true,
className: 'core-download-course',
priority: 1000
prefetchCourseData = {
prefetchCourseIcon: 'spinner'
};
protected buttons;
constructor(private navCtrl: NavController, private translate: TranslateService) {
this.downloadText = this.translate.instant('core.course.downloadcourse');
this.downloadingText = this.translate.instant('core.downloading');
protected isDestroyed = false;
protected courseStatusObserver;
constructor(private navCtrl: NavController, private translate: TranslateService, private courseHelper: CoreCourseHelperProvider,
private courseFormatDelegate: CoreCourseFormatDelegate, private domUtils: CoreDomUtilsProvider,
private courseProvider: CoreCourseProvider, eventsProvider: CoreEventsProvider, sitesProvider: CoreSitesProvider) {
// Listen for status change in course.
this.courseStatusObserver = eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.prefetchCourseData.prefetchCourseIcon = this.courseHelper.getCourseStatusIconFromStatus(data.status);
}
}, sitesProvider.getCurrentSiteId());
}
/**
* Component being initialized.
*/
ngOnInit() {
// @todo: Handle course prefetch.
// Determine course prefetch icon.
this.courseHelper.getCourseStatusIcon(this.course.id).then((icon) => {
this.prefetchCourseData.prefetchCourseIcon = icon;
if (icon == 'spinner') {
// Course is being downloaded. Get the download promise.
const promise = this.courseHelper.getCourseDownloadPromise(this.course.id);
if (promise) {
// There is a download promise. If it fails, show an error.
promise.catch((error) => {
if (!this.isDestroyed) {
this.domUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
}
});
} else {
// No download, this probably means that the app was closed while downloading. Set previous status.
this.courseProvider.setCoursePreviousStatus(this.course.id);
}
}
});
}
/**
* Open a course.
*/
openCourse(course) {
this.navCtrl.push('CoreCourseSectionPage', {course: course});
this.courseFormatDelegate.openCourse(this.navCtrl, course);
}
/**
* Prefetch the course.
*
* @param {Event} e Click event.
*/
prefetchCourse(e: Event) {
e.preventDefault();
e.stopPropagation();
this.courseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course).catch((error) => {
if (!this.isDestroyed) {
this.domUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
}
})
}
/**
* Component destroyed.
*/
ngOnDestroy() {
this.isDestroyed = true;
if (this.courseStatusObserver) {
this.courseStatusObserver.off();
}
}
}

View File

@ -1,7 +1,7 @@
<ng-template #eventTemplate let-event="event">
<a ion-item core-link text-wrap detail-none captureLink="true" class="core-course-module-handler item-media" [href]="event.url" [title]="event.name" [class.item-badge-right-phone]="event.action && event.action.showitemcount">
<img [src]="event.iconUrl" core-external-content alt="" role="presentation" *ngIf="event.iconUrl">
<p class="item-heading"><core-format-text [text]="event.name"></core-format-text></p>
<img item-start [src]="event.iconUrl" core-external-content alt="" role="presentation" *ngIf="event.iconUrl" class="core-module-icon">
<h2><core-format-text [text]="event.name"></core-format-text></h2>
<p>{{event.timesort * 1000 | coreFormatDate:"dfmediumdate" }} <core-format-text *ngIf="showCourse" [text]="event.course.fullnamedisplay"></core-format-text></p>
<button ion-button clear item-end class="hidden-phone" (click)="action($event, event.action.url)" [title]="event.action.name" [disabled]="!event.action.actionable" *ngIf="event.action">
{{event.action.name}}

View File

@ -17,6 +17,7 @@ import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
import { CoreUtilsProvider } from '../../../../providers/utils/utils';
import { CoreCourseProvider } from '../../../course/providers/course';
import * as moment from 'moment';
/**
@ -41,7 +42,8 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
future: any[] = [];
constructor(private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider,
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider) {
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider,
private courseProvider: CoreCourseProvider) {
this.loadMore = new EventEmitter();
}
@ -73,7 +75,7 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
return start <= event.timesort;
}).map((event) => {
// @todo: event.iconUrl = this.courseProvider.getModuleIconSrc(event.icon.component);
event.iconUrl = this.courseProvider.getModuleIconSrc(event.icon.component);
return event;
});
}

Some files were not shown because too many files have changed in this diff Show More