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

[PE-389-1][PE-1517] chore: remove the domain prop #51

Merged
merged 25 commits into from
Nov 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b3049cd
chore: remove the domain prop
luqven Oct 28, 2021
68f8eca
feat: create a search service endpoint
luqven Oct 28, 2021
e784009
chore: add on submit and change handlers
luqven Oct 28, 2021
abb1855
feat: add serach to asset browser
luqven Oct 28, 2021
28c1c5d
chore: change searchbar story props
luqven Oct 28, 2021
f66cc1c
chore: make search bar input width larger
luqven Oct 28, 2021
7c2b46d
chore: catch invalid api key errors
luqven Oct 28, 2021
dd17070
chore: change spinner color
luqven Oct 28, 2021
412062e
feat: display API warnings in asset browser
luqven Oct 28, 2021
d02a0e3
chore: add asset grid story placeholder prop
luqven Oct 28, 2021
66983b1
chore: create and export the cursor type
luqven Oct 28, 2021
67cd3e3
feat: create the pagination component
luqven Oct 28, 2021
30dde96
feat(imgix-api): store response cursor object
luqven Oct 28, 2021
0743306
refactor: lift asset-browser state into container
luqven Oct 28, 2021
018a110
refactor(asset-grid): render placeholder
luqven Oct 28, 2021
2ec1f53
feat: create asset browsner container
luqven Oct 28, 2021
2f75ae3
chore: update story props for asset grid & browser
luqven Oct 28, 2021
74ff793
chore: add todo
luqven Oct 28, 2021
bf4d1a5
chore: remove unused border
luqven Oct 28, 2021
769fc90
feat(asset-browser): add pagination
luqven Oct 28, 2021
095b514
chore: update grid style to show more assets
luqven Oct 28, 2021
1cfcfc2
chore: update jsdoc to use params tag
luqven Nov 2, 2021
f105d10
chore: remove console log
luqven Nov 2, 2021
0dbe72a
chore: replace any type with source type
luqven Nov 2, 2021
6c6e47d
chore: add more meaningful api key error message
luqven Nov 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion frontend/.storybook/preview.js
Expand Up @@ -6,4 +6,5 @@ export const parameters = {
date: /Date$/,
},
},
}
layout: "fullscreen",
};
158 changes: 90 additions & 68 deletions frontend/src/components/AssetBrowser/AssetBrowser.tsx
@@ -1,65 +1,109 @@
import React, { ReactElement } from "react";
import { ImgixGETSourcesData, ImgixGETAssetsData, CursorT } from "../../types";

import { AssetGrid } from "../grids/AssetGrid";
import { imgixAPI } from "../../services/imgixAPIService";
import { SearchBar } from "../forms/search/SearchBar";
import { LoadingSpinner } from "../LoadingSpinner";
import { SourceSelect } from "../buttons/dropdowns/SourceSelect";
import { ImgixGETSourcesData } from "../../types";

import "../../styles/AssetBrowser.css";

import Pagination from "../buttons/Pagination";
interface Props {
apiKey: string;
errors: string[];
loading: boolean;
sources: ImgixGETSourcesData;
assets: ImgixGETAssetsData;
cursor: CursorT;
query: string;
selectedSource: ImgixGETSourcesData[0] | null;
setQuery: (input: string) => any;
setLoading: (loading: boolean) => any;
setSelectedSource: (source: ImgixGETSourcesData[0]) => any;
requestAssetsFromSource: ({
source,
cursor,
query,
}: {
source: ImgixGETSourcesData[0];
cursor?: CursorT;
query?: string;
}) => Promise<void>;
}
// TODO(luis): Refactor this component into smaller components
export function AssetBrowser({
errors,
loading,
sources,
assets,
cursor,
query,
selectedSource,
setQuery,
setLoading,
setSelectedSource,
requestAssetsFromSource,
}: Props): ReactElement {
/**
* Handle pagination button clicks and pass the new cursor to the parent
* @param offset - Either 1 or -1. 1 for next page, -1 for previous page
* @returns {Promise} A promise that resolves to the new assets and cursor
*/
const handlePageChange = (offset: number) => {
// TODO(luis): handle undefined source better
if (!selectedSource) return;
// update the cursor position with the offset
const currentPage = Number(cursor.current) || 0;
const limit = cursor.limit || 12;
const delta = offset * limit;
const nextPage = "" + (currentPage + delta);
const newCursor = { ...cursor, current: nextPage };

export function AssetBrowser({ apiKey }: Props): ReactElement {
const [loading, setLoading] = React.useState(true);
const [sources, setSources] = React.useState<ImgixGETSourcesData>([]);
const [selectedSource, setSelectedSource] = React.useState<
ImgixGETSourcesData[0]
>();
const [assets, setAssets] = React.useState<any[]>([]);
// request the assets from the new cursor position
requestAssetsFromSource({
source: selectedSource,
cursor: newCursor,
query,
});
};

/**
* Request the assets from the selected source
* @param sourceId - The id of the source to request assets from
* @returns {Promise} A promise that resolves to the new assets and cursor
*/
const handleSourceSelect = (sourceId: string) => {
setLoading(true);
// store the selected source and fetch its assets
const source = sources.find(
(currentSource) => currentSource.id === sourceId
(currentSource: ImgixGETSourcesData[0]) => currentSource.id === sourceId
);
if (!source) return;
setSelectedSource(source);

imgixAPI.sources.assets
.get(apiKey, source.id)
.then((res) => {
// store the source' assets
setLoading(false);
setAssets(res.data);
})
.catch((err) => {
console.log(err);
});
requestAssetsFromSource({ source });
};

React.useEffect(() => {
// if no API key is provided, don't fetch sources
if (!apiKey) {
setLoading(false);
} else {
setLoading(true);
// fetch the sources when the component mounts
imgixAPI.sources.get(apiKey).then((resp) => {
setLoading(false);
setSources(resp.data);
});
}
}, [apiKey]);
/**
* Handle the search bar input and pass the new query to the parent
* @param query - The query to search for
* @returns {Promise} A promise that resolves to the new assets and cursor
*/
const handleSearch = (query: string) => {
setLoading(true);
setQuery(query);
if (!selectedSource) return;
requestAssetsFromSource({ source: selectedSource, query });
};

/**
* Parse the domain from the source attributes
* @param source - The source to request assets from
* @returns {string} Either a custom source name or the default source name,
* `<source.attribute.name>.imgix.net`
*/
const parseSourceDomain = (source: ImgixGETSourcesData[0]) => {
// TODO(luis): add tests to better handle this behavior
// If the source has no custom domains, return the source name as the domain
if (!source) return "";
if (!source || !source.attributes) return "";

const customDomains = source?.attributes?.custom_domains;
if (!customDomains || !customDomains.length) {
return source.attributes.name + ".imgix.net";
Expand All @@ -69,42 +113,20 @@ export function AssetBrowser({ apiKey }: Props): ReactElement {
};

const domain = parseSourceDomain(selectedSource as ImgixGETSourcesData[0]);
const hasSources = sources && !!sources.length;
const hasAssets = assets && !!assets.length && !!domain.length;

// create placeholder to show when no sources or assets are available
let placeHolderText;
if (!hasSources) {
placeHolderText = "No sources found";
} else if (selectedSource && !hasAssets && !loading) {
placeHolderText = "Selected source has no assets.";
} else {
placeHolderText = "Select a source.";
}

const placeholder =
!loading && (!assets || !assets.length) ? (
<div className="ix-grid">
<div className="ix-grid ix-grid-item-placeholder ">
<div>
<div>{placeHolderText}</div>
</div>
</div>
</div>
) : null;

return (
<div className="ix-asset-browser">
<div className="ix-asset-title-bar-container">
<SourceSelect sources={sources} handleSelect={handleSourceSelect} />
<SearchBar />
<SearchBar handleSubmit={handleSearch} />
</div>
<LoadingSpinner loading={loading} />
{placeholder ? (
placeholder
) : (
<AssetGrid domain={domain} assets={assets} />
)}
<AssetGrid
domain={domain}
assets={assets}
loading={loading}
errors={errors}
/>
<Pagination cursor={cursor} handlePageChange={handlePageChange} />
<div className="ix-asset-meta-information-container"></div>
</div>
);
Expand Down