Skip to content

Commit

Permalink
Aws S3 storage #256
Browse files Browse the repository at this point in the history
  • Loading branch information
treoden committed Oct 31, 2023
1 parent 13269dd commit 9c95f6b
Show file tree
Hide file tree
Showing 20 changed files with 3,273 additions and 129 deletions.
2,616 changes: 2,612 additions & 4 deletions package-lock.json

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions packages/azure_file_storage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Azure storage extension for EverShop

This extension allows you to store your EverShop files on Azure Blob Storage.

> **Note**: This extension requires EverShop version 1.0.0-rc.9 or higher.
## Installation guide

### Step 1: Install the extension using npm:

```bash
npm install @evershop/azure_file_storage
```

### Step 2: Enable the extension

Edit the `config/default.json` file in the root directory of your EverShop installation and add the following line to the `extensions` section:

```json
{
...,
"system": {
...,
"extensions": [
...,
{
"name": "azure_file_storage",
"resolve": "node_modules/@evershop/azure_file_storage",
"enabled": true,
"priority": 10
}
]
}
}
```

### Step 3: Add the Azure storage connection string to the environment variables

Edit the `.env` file:

```bash
AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=myevershop;AccountKey=+b1/nrwkpOF5DZCybDqSDFDdfGCQSbx8eua3y7sadgfdgdfAdNNbns6xMNh+EeE0b10uc0ZJ+AStvBx8pg==;EndpointSuffix=core.windows.net"
AZURE_STORAGE_CONTAINER_NAME="images"
```

### Step 4: Active the AWS S3 storage

Edit the `config/default.json` file in the root directory of your EverShop installation and add the following line to the `file_storage` section:

```json
{
...,
"file_storage": "azure"
}
```

### Step 4: Run the build command

```bash
npm run build
```

> **Note**: You can get the connection string from the Azure portal.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ module.exports = async (request, response, delegate, next) => {
response.json({
error: {
status: INTERNAL_SERVER_ERROR,
message: 'Error uploading images to Azure Blob Storage'
message: 'Error listing files from Azure Blob Storage'
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ async function resizeAndUploadImage(

// Resize the image
const resizedImageBuffer = await sharp(originalImageBuffer)
.resize({ width, height })
.resize({ width, height, fit: 'inside' })
.toBuffer();

// Upload the resized image
Expand Down
19 changes: 12 additions & 7 deletions packages/evershop/bin/lib/startUp.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { Handler } = require('@evershop/evershop/src/lib/middleware/Handler');
const spawn = require('cross-spawn');
const path = require('path');
const { error } = require('@evershop/evershop/src/lib/log/debuger');
const isDevelopmentMode = require('@evershop/evershop/src/lib/util/isDevelopmentMode');
const { createApp } = require('./app');
const normalizePort = require('./normalizePort');
const onListening = require('./onListening');
Expand Down Expand Up @@ -55,16 +56,20 @@ module.exports.start = async function start(cb) {
server.listen(port);

// Spawn the child process to manage events
const child = spawn(
'node',
[path.resolve(__dirname, '../../src/lib/event/event-manager.js')],
{
stdio: 'inherit'
}
);
const args = [
path.resolve(__dirname, '../../src/lib/event/event-manager.js')
];
if (isDevelopmentMode() || process.argv.includes('--debug')) {
args.push('--debug');
}
const child = spawn('node', args, {
stdio: 'inherit'
});

child.on('error', (err) => {
error(`Error spawning event processor: ${err}`);
});

child.unref();
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,12 @@ query Query($productId: ID!) {
editUrl
updateApi
image {
uniqueId
url: thumb
path
uuid
url
}
gallery {
uniqueId
url: origin
path
uuid
url
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Category {
The `CategoryImage` type represents a category image object.
"""
type CategoryImage {
path: String!
alt: String!
url: String!
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ module.exports = {
}
},
image: (category) => {
const { image } = category;
const { image, name } = category;
if (!image) {
return null;
} else {
return {
path: image,
url: `/assets${image}`
alt: name,
url: image
};
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ const { select } = require('@evershop/postgres-query-builder');
const uniqid = require('uniqid');
const { buildUrl } = require('@evershop/evershop/src/lib/router/buildUrl');
const { camelCase } = require('@evershop/evershop/src/lib/util/camelCase');
const {
getProductsBaseQuery
} = require('../../../../services/getProductsBaseQuery');

module.exports = {
Product: {
Expand Down Expand Up @@ -160,21 +163,7 @@ module.exports = {
},
Variant: {
product: async ({ productId }, _, { pool }) => {
const query = select().from('product');
query
.leftJoin('product_description')
.on(
'product_description.product_description_product_id',
'=',
'product.product_id'
);
query
.innerJoin('product_inventory')
.on(
'product_inventory.product_inventory_product_id',
'=',
'product.product_id'
);
const query = getProductsBaseQuery();
query.where('product_id', '=', productId);
const result = await query.load(pool);
if (!result) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable jsx-a11y/label-has-associated-control */
import PropTypes from 'prop-types';
import React, { useRef, useState } from 'react';
import { toast } from 'react-toastify';
Expand Down Expand Up @@ -73,83 +74,85 @@ export default function Image({ category, imageUploadUrl }) {
}
>
<Card.Session>
{!image && (
<label
htmlFor="categoryImageUpload"
className="flex flex-col justify-center image-uploader"
>
{loading === true && (
<div className="loading flex justify-center">
<div className="self-center">
<svg
style={{ display: 'block', shapeRendering: 'auto' }}
viewBox="0 0 100 100"
preserveAspectRatio="xMidYMid"
>
<circle
cx="50"
cy="50"
fill="none"
stroke="var(--primary)"
strokeWidth="10"
r="43"
strokeDasharray="202.63272615654165 69.54424205218055"
>
<animateTransform
attributeName="transform"
type="rotate"
repeatCount="indefinite"
dur="1s"
values="0 50 50;360 50 50"
keyTimes="0;1"
/>
</circle>
</svg>
</div>
<div className="relative">
{!image && (
<label
htmlFor="categoryImageUpload"
className="flex flex-col justify-center image-uploader"
>
<div className="uploader-icon flex justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z"
clipRule="evenodd"
/>
</svg>
</div>
)}
<div className="uploader-icon flex justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z"
clipRule="evenodd"
<div className="flex justify-center">
<Button
title="Add image"
variant="default"
onAction={() => ref.current.click()}
/>
</svg>
</div>
<div className="flex justify-center">
<Button
title="Add image"
variant="default"
onAction={() => ref.current.click()}
/>
</div>
<div className="flex justify-center mt-1">
<span style={{ color: '#6d7175', fontSize: '1.2rem' }}>
click to upload an image
</span>
</div>
<div className="flex justify-center mt-1">
<span style={{ color: '#6d7175', fontSize: '1.2rem' }}>
click to upload an image
</span>
</div>
</label>
)}
{image && (
<div className="category-image">
<img src={image.url} alt={' '} />
</div>
</label>
)}
{image && (
<div className="category-image">
<img src={image.url} alt={' '} />
)}
{image && <input type="hidden" value={image.url} name="image" />}
{!image && <input type="hidden" value="" name="image" />}
<div className="invisible" style={{ width: '1px', height: '1px' }}>
<input
id="categoryImageUpload"
type="file"
onChange={onChange}
ref={ref}
/>
</div>
)}
{image && <input type="hidden" value={image.path} name="image" />}
{!image && <input type="hidden" value="" name="image" />}
<div className="invisible" style={{ width: '1px', height: '1px' }}>
<input
id="categoryImageUpload"
type="file"
onChange={onChange}
ref={ref}
/>
{loading === true && (
<div className="category__image__loading flex justify-center">
<div className="self-center">
<svg
style={{ display: 'block', shapeRendering: 'auto' }}
viewBox="0 0 100 100"
preserveAspectRatio="xMidYMid"
>
<circle
cx="50"
cy="50"
fill="none"
stroke="var(--primary)"
strokeWidth="10"
r="43"
strokeDasharray="202.63272615654165 69.54424205218055"
>
<animateTransform
attributeName="transform"
type="rotate"
repeatCount="indefinite"
dur="1s"
values="0 50 50;360 50 50"
keyTimes="0;1"
/>
</circle>
</svg>
</div>
</div>
)}
</div>
</Card.Session>
</Card>
Expand All @@ -159,7 +162,6 @@ export default function Image({ category, imageUploadUrl }) {
Image.propTypes = {
category: PropTypes.shape({
image: PropTypes.shape({
path: PropTypes.string,
url: PropTypes.string
})
}),
Expand All @@ -179,7 +181,6 @@ export const query = `
query Query {
category(id: getContextValue("categoryId", null)) {
image {
path
url
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,15 @@
max-height: 100%;
}
}

.category__image__loading{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
svg {
width: 25px;
height: 25px;
}
}
Loading

0 comments on commit 9c95f6b

Please sign in to comment.