Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.5.0: Quartz Energy app release + Quartz Solar improvements & zoom #513

Merged
merged 134 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
134 commits
Select commit Hold shift + click to select a range
8981cde
add chart with zoom
rachel-labri-tipton Dec 14, 2023
a17a986
adjust the yMax for the national chart
rachel-labri-tipton Dec 14, 2023
de49e5f
chart zoom on the x axis
rachel-labri-tipton Dec 18, 2023
95fd00a
remove option to select axes and labels
rachel-labri-tipton Jan 17, 2024
5898cc8
change close button for zoom
rachel-labri-tipton Jan 17, 2024
cb2d5d5
use new function getZoomYMax to get ymax
rachel-labri-tipton Jan 17, 2024
ebb93cd
Added cypress, login func. & simple test
braddf Aug 23, 2023
2d08f22
Update tests; add map id tags for test targets
braddf Jan 17, 2024
d789bc3
apply zoom to all charts simultaneously
rachel-labri-tipton Jan 17, 2024
feafcbe
set yMax when charts are zoomed
rachel-labri-tipton Jan 17, 2024
9f5464a
current work on all charts with same zoom level
rachel-labri-tipton Jan 22, 2024
5648137
Added cypress, login func. & simple test
braddf Aug 23, 2023
4427753
save initial work on tests
rachel-labri-tipton Jan 16, 2024
666d376
Tweak globalZoom func. & disable on Sites
braddf Jan 22, 2024
5e944c5
change circle so that area is proportional to expected PV
peterdudfield Jan 24, 2024
8a8cd51
use Math.sqrt
peterdudfield Jan 24, 2024
6fec0fc
halfway between linear and area
peterdudfield Jan 24, 2024
26caa43
Disable Sentry on local dev & add env var
braddf Jan 25, 2024
b1e5464
update README
braddf Jan 25, 2024
13ef9a3
add github workflow
peterdudfield Feb 5, 2024
30f27ec
fix
peterdudfield Feb 5, 2024
190727a
fix 2
peterdudfield Feb 5, 2024
2f2662f
add codecov
peterdudfield Feb 5, 2024
8126a18
add coverage
peterdudfield Feb 5, 2024
051b4e6
removed codecov for the moment
peterdudfield Feb 5, 2024
0d7d297
fix possible merge conflict losses
braddf Feb 5, 2024
d73b941
Merge pull request #464 from openclimatefix/issue/ci
peterdudfield Feb 5, 2024
8164485
Merge pull request #461 from openclimatefix/issue/437-blob-size
rachel-labri-tipton Feb 6, 2024
4883743
fix cypress/turbo build errors
braddf Feb 9, 2024
1b36d58
fix test; remove turbo in package.json
braddf Feb 9, 2024
9a47351
Merge pull request #470 from openclimatefix/new-cypress-testing
rachel-labri-tipton Feb 15, 2024
56b4d57
Bugfix for map flashing issue 🤞🏻
braddf Feb 23, 2024
a8189d1
Improve bugfix for map flashing issue
braddf Feb 23, 2024
b590065
adjust zoomYMax for GSPs
rachel-labri-tipton Mar 18, 2024
f86105d
update the globalZoomArea to select right to left
rachel-labri-tipton Mar 19, 2024
cf23a22
add zoom out icon
rachel-labri-tipton Mar 20, 2024
7d83dce
fix issue with setting time of interest while zooming
rachel-labri-tipton Apr 10, 2024
f5f6108
code clean up
rachel-labri-tipton Apr 11, 2024
ee831a7
Merge branch 'staging' into development
braddf Apr 11, 2024
4598f69
Merge staging back & fix tests
braddf Apr 11, 2024
5476b35
Merge pull request #456 from openclimatefix/issue/identical-zoom-for-…
braddf Apr 15, 2024
e9c25bb
Fade out chart data up-to-date status
braddf Apr 15, 2024
b12e0ba
Fix zoom reset time now bug, mostly
braddf Apr 15, 2024
70820a7
Fix delta calc bug
braddf Apr 17, 2024
9579f73
Fix delta buckets bug
braddf Apr 17, 2024
811c803
Fix delta buckets layout/styling
braddf Apr 17, 2024
a287520
Merge pull request #503 from openclimatefix/development
braddf Apr 17, 2024
f406f34
new nextjs app initial commit
braddf Feb 8, 2024
af7505f
add logo; fix build type errors
braddf Feb 8, 2024
27dd367
add OCF greys from design files; fix config
braddf Feb 12, 2024
be94d27
add initial apiClient, types, data fetching, chart
braddf Feb 15, 2024
9770daa
update title
braddf Feb 15, 2024
2c29f06
fix linting errors
braddf Feb 15, 2024
b64894f
update api to proxied quartz route
braddf Feb 15, 2024
358fad7
Switch wind/solar on graphs, solar on bottom
braddf Feb 15, 2024
a5f4b4c
update icons and add wide sidebar
rachel-labri-tipton Feb 13, 2024
7184edf
add narrow sidebar styling
rachel-labri-tipton Feb 13, 2024
678d13d
adjust container width
rachel-labri-tipton Feb 13, 2024
48cbd05
adding sidebar components
rachel-labri-tipton Feb 14, 2024
8745ccb
add mini-cards for collapsed sidebar
rachel-labri-tipton Feb 15, 2024
fab39d9
move left arrow to the right of sidebar
rachel-labri-tipton Feb 15, 2024
49cf43f
fix text color
rachel-labri-tipton Feb 19, 2024
574948b
sidebar with card and minicard components
rachel-labri-tipton Feb 19, 2024
3c9c7c4
fix linting errors
rachel-labri-tipton Feb 19, 2024
fc63dcc
fix linting for time label:
rachel-labri-tipton Feb 19, 2024
c128cd2
fix type error in card component
rachel-labri-tipton Feb 19, 2024
0c57138
Amend corrected forecast to display MW
braddf Feb 19, 2024
b49c89a
Round generation values down to minute
braddf Feb 19, 2024
383bd48
Flip and sort formatted Chart data
braddf Feb 21, 2024
4348630
resample generation to 15 minutes
peterdudfield Feb 21, 2024
6e46118
run prettier
peterdudfield Feb 21, 2024
2a43016
role back
peterdudfield Feb 21, 2024
305feed
Add now reference line in Indian Standard Time
braddf Feb 21, 2024
f5245f9
adjust schema
peterdudfield Feb 21, 2024
70c658d
use query object
peterdudfield Feb 21, 2024
6246077
split past/future forecast and style
braddf Feb 23, 2024
a7c70ff
seeing if pre-commit runs
rachel-labri-tipton Feb 19, 2024
27bc8fa
adding actual data to SideBar
rachel-labri-tipton Feb 19, 2024
580de1d
adding data to the sidebar
rachel-labri-tipton Feb 22, 2024
0039728
pushing work for pair code session
rachel-labri-tipton Feb 26, 2024
949a3bc
sidebar with actual data
rachel-labri-tipton Feb 28, 2024
bdfea77
fix chart linting errors
rachel-labri-tipton Feb 28, 2024
fef3b15
format axes ticks & add label
braddf Feb 27, 2024
0f2e711
add check for chartData timestamp
braddf Feb 27, 2024
274b156
format tooltip
braddf Feb 27, 2024
b49bebb
format tooltip nulls; show null gaps charts
braddf Feb 28, 2024
6800340
Add legend; refactor into components
braddf Mar 5, 2024
a454282
adding actual data to SideBar
rachel-labri-tipton Feb 19, 2024
2a919fb
add chevron buttons to sidebar
rachel-labri-tipton Mar 4, 2024
cc8b87a
fix type error in icon file
rachel-labri-tipton Mar 4, 2024
dd7f14f
add global state for showing and hiding lines
rachel-labri-tipton Mar 4, 2024
bbec79c
add working toggle to turn lines on and off
rachel-labri-tipton Mar 5, 2024
91a3438
add toggles to cards and mini-cards
rachel-labri-tipton Mar 7, 2024
75aee8d
add energyTag to card
rachel-labri-tipton Mar 7, 2024
3f16436
Rebase onto india-mvp; remove old Charts file
braddf Mar 7, 2024
8539485
Specify createGlobalState return type explicitly
braddf Mar 7, 2024
28468de
adding actual data to SideBar
rachel-labri-tipton Feb 19, 2024
0419737
add global state again for toggle
rachel-labri-tipton Mar 7, 2024
d6bda9f
remove old Charts file
rachel-labri-tipton Mar 7, 2024
f98dc81
fix duplication error
rachel-labri-tipton Mar 7, 2024
0e60ab2
Add combined tooltip vals; style changes
braddf Mar 8, 2024
5a7868b
Update sidebar actual colors
braddf Mar 8, 2024
bd27f09
Toggle other gen type on when none selected
braddf Mar 8, 2024
c17c579
Add temp header profile icon
braddf Mar 8, 2024
288c650
Sidebar padding/styling
braddf Mar 8, 2024
2c524a8
Disable pointer on now label hover^
braddf Mar 12, 2024
9778777
Make combinedData global; add user menu
braddf Mar 13, 2024
1f03b3c
update solar generation to reflect correct value
rachel-labri-tipton Mar 12, 2024
44134ef
small fix
rachel-labri-tipton Mar 13, 2024
985edcc
Add downloadCsv function first draft
braddf Mar 15, 2024
9cfa800
Show/Hide toggled forecasts in tooltip
braddf Mar 20, 2024
3468754
Sidebar layout/styling
braddf Mar 21, 2024
d8c3481
Fix gap in area chart
braddf Mar 21, 2024
98b74ac
Fix CSV & amend format/filename
braddf Apr 4, 2024
69269c0
Fix overflow horizontal scroll bug
braddf Apr 4, 2024
376a0bd
Add day name x axis
braddf Apr 4, 2024
b73427d
Solid now line
braddf Apr 4, 2024
a3c585d
Sidebar: GW -> MW
braddf Apr 5, 2024
a569775
mini sidebar number format
braddf Apr 5, 2024
f3f5653
amend csv: KW -> MW
braddf Apr 5, 2024
95d908a
fix chart data bug(s) and now gap; add test
braddf Apr 5, 2024
9835e73
fix build error(s)
braddf Apr 5, 2024
1265168
fix nowcasting build error(s)
braddf Apr 5, 2024
e880bad
No data label in tooltip
braddf Apr 5, 2024
5788006
Add refetch param
braddf Apr 8, 2024
7c2891c
move wind below solar in sidebar
peterdudfield Mar 22, 2024
815dc23
Dynamic ordering in tooltip values
braddf Apr 11, 2024
bbcd711
Update packages & bring apps in line
braddf Apr 19, 2024
913696b
Fix test errors
braddf Apr 19, 2024
a029b63
Fix CI test setup
braddf Apr 22, 2024
1267f1d
Tweak CI test setup
braddf Apr 22, 2024
ed74fe2
Merge pull request #471 from openclimatefix/india-mvp
braddf May 8, 2024
7c2c1dc
Merge pull request #512 from openclimatefix/development
braddf May 8, 2024
6f88da2
Bump version
braddf May 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/yarn_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Node CI

on: [push]

jobs:
build:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x]

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: install yarn
run: |
cd apps/nowcasting-app
yarn install
- name: build & start app
run: |
cd apps/nowcasting-app
yarn build
- name: run tests
run: |
cd apps/nowcasting-app
yarn start & sleep 5 && yarn test --coverage --coverageDirectory=../..
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
node_modules
.turbo
build/**
dist/**
.next/**
3 changes: 3 additions & 0 deletions apps/nowcasting-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ AUTH0_ISSUER_BASE_URL='https://nowcasting-dev.eu.auth0.com'
AUTH0_CLIENT_ID='<client id>'
# Your Auth0 application's Client Secret
AUTH0_CLIENT_SECRET='<client secret>'
# Disable Sentry on local to avoid noise
# (should default to off in development env anyway but just to make sure)
NEXT_PUBLIC_SENTRY_DISABLED='true'
```

### Running the App
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,14 @@ const EndpointStatusList = <K extends NationalEndpointStates | SitesEndpointStat
}: EndpointStatusListProps<K>) => {
const endpointsArray = Array.from(Object.entries(endpointStates));
return (
<div className="absolute -top-4 right-4 flex items-center h-9 z-40">
<div
className={`absolute -top-4 right-4 flex items-center h-9 ${isLoadingData ? "z-40" : "z-0"}`}
>
<div
className={`chart-data-loading-message flex flex-row relative h-6 cursor-default justify-between items-center rounded-sm bg-mapbox-black ${
isLoadingData ? "pr-2 pl-1.5" : "bg-mapbox-black-600 px-1.5"
isLoadingData
? "pr-2 pl-1.5"
: "bg-mapbox-black-600 px-1.5 fade-out pointer-events-none select-none"
}`}
>
{!!isLoadingData && <SpinnerTextInline className="mr-2" />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const GspDeltaColumn: FC<{
let hasRows = false;
return (
<>
<div className={`flex flex-col flex-1 mb-24 ${!negative ? "pl-3" : "pr-3 "}`}>
<div className={`flex flex-col flex-1 mb-24 ${!negative ? "pl-1" : "pr-1 "}`}>
{deltaArray.sort(sortFunc).map((gspDelta) => {
let bucketColor = "";
let dataKey = "";
Expand Down Expand Up @@ -150,7 +150,7 @@ const GspDeltaColumn: FC<{
gspDelta.delta > 0 ? `bg-ocf-delta-900` : `bg-ocf-delta-100`
}`;

const selectedClasses = `${bucketColor} transition duration-200 ease-out hover:ease-in items-end`;
const selectedClasses = `${bucketColor} transition duration-200 ease-out hover:ease-in items-start`;

const selectedDeltaClass = `bg-ocf-gray-800 ${bucketColor} items-end`;

Expand All @@ -165,30 +165,49 @@ const GspDeltaColumn: FC<{
onClick={() => setClickedGspId(gspDelta.gspId)}
>
<div
className={`static items-center flex flex-1 py-2 justify-between pl-1 pr-1 ${
className={`static items-start xl:items-center flex flex-col xl:flex-row flex-1 py-2 justify-between pl-1 pr-1 ${
clickedGspId === gspDelta.gspId ? selectedDeltaClass : selectedClasses
} ${gspDelta.delta > 0 ? `border-l-8` : `border-r-8`}`}
key={`gspCol${gspDelta.gspId}`}
>
<div className="flex-initial pl-1 max-w-[35%] dash:max-w-full">
<div className="flex-initial flex justify-between self-stretch items-center pl-1 dash:max-w-full">
<span className="">{gspDelta.gspRegion}</span>
{/* normalized percentage: delta value/gsp installed mw capacity */}
<div className="block flex-initial xl:hidden">
<DeltaForecastLabel
tip={
<div className="w-28 text-xs">
<p>{"Normalized Delta"}</p>
</div>
}
>
<div className="flex text-right opacity-80 text-sm">
<p>
{negative ? "-" : "+"}
{deltaNormalizedPercentage}%
</p>
</div>
</DeltaForecastLabel>
</div>
</div>
<div className="flex flex-initial flex-end justify-around items-center">
<div className="flex flex-initial flex-end justify-between self-stretch items-center">
{/* normalized percentage: delta value/gsp installed mw capacity */}
<DeltaForecastLabel
tip={
<div className="w-28 text-xs">
<p>{"Normalized Delta"}</p>
<div className="hidden xl:block">
<DeltaForecastLabel
tip={
<div className="w-28 text-xs">
<p>{"Normalized Delta"}</p>
</div>
}
>
<div className="flex pr-3 text-right opacity-80 text-sm">
<p>
{negative ? "-" : "+"}
{deltaNormalizedPercentage}%
</p>
</div>
}
>
<div className="flex pr-3 text-right opacity-80 text-sm">
<p>
{negative ? "-" : "+"}
{deltaNormalizedPercentage}%
</p>
</div>
</DeltaForecastLabel>
</DeltaForecastLabel>
</div>

{/* delta value in mw */}
<DeltaForecastLabel
Expand All @@ -210,21 +229,23 @@ const GspDeltaColumn: FC<{
</DeltaForecastLabel>

{/* currentYield/forecasted yield */}
<DeltaForecastLabel
tip={
<div className="w-28 text-xs">
<p>{"Actual PV / Forecast"}</p>
</div>
}
>
<div className="flex flex-col pr-1 text-left font-semibold text-sm">
<div>
{Number(gspDelta.currentYield).toFixed(0)}/
{Number(gspDelta.forecast).toFixed(0)}{" "}
<span className={`opacity-80 text-xs font-thin`}>MW</span>
<div>
<DeltaForecastLabel
tip={
<div className="w-28 text-xs">
<p>{"Actual PV / Forecast"}</p>
</div>
}
>
<div className="flex flex-col pr-1 text-right font-semibold text-sm">
<div>
{Number(gspDelta.currentYield).toFixed(0)}/
{Number(gspDelta.forecast).toFixed(0)}{" "}
<span className={`opacity-80 text-xs font-thin`}>MW</span>
</div>
</div>
</div>
</DeltaForecastLabel>
</DeltaForecastLabel>
</div>
</div>
</div>
<div className={`absolute bottom-0 right-0 left-0 ${bucketColor}`}>
Expand All @@ -233,7 +254,12 @@ const GspDeltaColumn: FC<{
gspDelta.delta > 0 ? `bottom-0 flex-row-reverse ml-2` : `mr-2`
}`}
>
<div className={tickerColor} style={{ width: `1px` }}></div>
<div
className={`${
clickedGspId === gspDelta.gspId ? `h-2.5` : `h-2`
} ${progressLineColor}`}
style={{ width: `1px` }}
></div>
<div
className={`${
clickedGspId === gspDelta.gspId ? `h-1.5` : `h-1`
Expand Down Expand Up @@ -273,6 +299,7 @@ const DeltaChart: FC<DeltaChartProps> = ({ className, combinedData, combinedErro
const [show4hView] = useGlobalState("show4hView");
const [clickedGspId, setClickedGspId] = useGlobalState("clickedGspId");
const [visibleLines] = useGlobalState("visibleLines");
const [globalZoomArea] = useGlobalState("globalZoomArea");
const [selectedBuckets] = useGlobalState("selectedBuckets");
const [selectedISOTime, setSelectedISOTime] = useGlobalState("selectedISOTime");
const [timeNow] = useGlobalState("timeNow");
Expand All @@ -285,7 +312,8 @@ const DeltaChart: FC<DeltaChartProps> = ({ className, combinedData, combinedErro
const halfHourAgo = `${formatISODateString(new Date(halfHourAgoDate).toISOString())}:00Z`;
const hasGspPvInitialForSelectedTime = !!combinedData.pvRealDayInData?.find(
(d) =>
d.datetimeUtc === `${formatISODateString(selectedTimeHalfHourSlot.toISOString())}:00+00:00`
d.datetimeUtc.slice(0, 16) ===
`${formatISODateString(selectedTimeHalfHourSlot.toISOString())}`
);

const {
Expand Down
14 changes: 10 additions & 4 deletions apps/nowcasting-app/components/charts/forecast-header/ui.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from "react";
import { theme } from "../../../tailwind.config";
import { ClockIcon } from "../../icons/icons";
import ForecastLabel from "../../national_forecast_labels";
Expand All @@ -18,7 +17,10 @@ export const ForecastHeadlineFigure: React.FC<{
: "dash:3xl:text-6xl dash:xl:text-5xl lg:text-3xl"
}`;
return (
<div className="flex gap-3 items-center m-auto h-10 dash:h-14 justify-between">
<div
data-test="pvlive-ocf-headline-figure"
className="flex gap-3 items-center m-auto h-10 dash:h-14 justify-between"
>
<div className="flex flex-1 self-center items-center justify-center">
<div className={`flex items-center ${textSizeClasses}`}>
<ForecastLabel
Expand Down Expand Up @@ -105,7 +107,10 @@ export const NextForecast: React.FC<{ pv: string; tip: string; time: string; col
color = yellow
}) => {
return (
<div className="flex gap-3 items-center m-auto h-10 dash:h-14 justify-between">
<div
data-test="forecast-label-tooltip"
className="flex gap-3 items-center m-auto h-10 dash:h-14 justify-between"
>
<ForecastLabel
className="dash:order-2"
tip={
Expand Down Expand Up @@ -140,6 +145,7 @@ export const NextForecast: React.FC<{ pv: string; tip: string; time: string; col
};

type ForecastHeaderProps = {
children: React.ReactNode;
forecastNextPV: string;
forecastPV: string;
actualPV: string;
Expand All @@ -158,7 +164,7 @@ const ForecastHeaderUI: React.FC<ForecastHeaderProps> = ({
forecastNextTimeOnly
}) => {
return (
<div className="flex content-between bg-ocf-gray-800 h-auto">
<div data-test="national-chart-header" className="flex content-between bg-ocf-gray-800 h-auto">
<div className="text-white dash:3xl:text-5xl dash:2xl:text-4xl dash:xl:text-3xl dash:tracking-wide lg:text-2xl md:text-lg text-base font-black m-auto ml-5 flex justify-evenly">
National
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { CloseButtonIcon, DownArrow, UpArrow } from "../../icons/icons";
import { ForecastHeadlineFigure } from "../forecast-header/ui";
import { DeltaHeaderBlock } from "../delta-view/delta-header-block";
import React, { FC } from "react";

type ForecastHeaderGSPProps = {
title: string;
Expand All @@ -14,9 +14,10 @@ type ForecastHeaderGSPProps = {
forecastPV?: string;
forecastNextTimeOnly?: string;
forecastNextPV?: string;
children?: React.ReactNode;
};

const ForecastHeaderGSP: React.FC<ForecastHeaderGSPProps> = ({
const ForecastHeaderGSP: FC<ForecastHeaderGSPProps> = ({
title,
deltaView,
deltaValue,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { FC } from "react";
import RemixLine from "../remix-line";
import useFormatChartData from "../use-format-chart-data";
import {
Expand All @@ -12,6 +11,7 @@ import useGetGspData from "./use-get-gsp-data";
import useGlobalState, { get30MinNow, getNext30MinSlot } from "../../helpers/globalState";
import Spinner from "../../icons/spinner";
import { ForecastValue } from "../../types";
import React, { FC } from "react";

// We want to have the ymax of the graph to be related to the capacity of the GspPvRemixChart
// If we use the raw values, the graph looks funny, i.e y major ticks are 0 100 232
Expand Down Expand Up @@ -63,7 +63,6 @@ const GspPvRemixChart: FC<{
console.log(errors);
return <div>failed to load</div>;
}

const now30min = formatISODateString(get30MinNow());
const dataMissing = !gspForecastDataOneGSP || !pvRealDataIn || !pvRealDataAfter;
const forecastAtSelectedTime: NonNullable<typeof gspForecastDataOneGSP>[number] =
Expand Down
1 change: 1 addition & 0 deletions apps/nowcasting-app/components/charts/pv-remix-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const PvRemixChart: FC<{
const { stopTime, resetTime } = useStopAndResetTime();
const selectedTime = formatISODateString(selectedISOTime || new Date().toISOString());
const [loadingState] = useGlobalState("loadingState");
const [globalZoomArea] = useGlobalState("globalZoomArea");

const {
nationalForecastData,
Expand Down
Loading
Loading