Skip to content

Commit

Permalink
Merge pull request #2 from yale-fortunoff/FOR-10-add-aviary-video-blocks
Browse files Browse the repository at this point in the history
FOR-10 add aviary video blocks
  • Loading branch information
jakekara authored Jun 5, 2022
2 parents 6aad47f + 8d31c94 commit a71baf5
Show file tree
Hide file tree
Showing 16 changed files with 2,284 additions and 2,079 deletions.
15 changes: 15 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[build]
# Directory to change to before starting a build.
# This is where we will look for package.json/.nvmrc/etc.
# If not set, defaults to the root directory.
# base = "project/"

# Directory that contains the deploy-ready HTML files and
# assets generated by the build. This is relative to the base
# directory if one has been set, or the root directory if
# a base has not been set. This sample publishes the directory
# located at the absolute path "root/project/build-output"
publish = "build/"

# Default build command.
command = "npm run fetch-test-data && npm run build"
12 changes: 11 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,20 @@
"post-deploy:zip": "zip -r public.zip public -x '.DS_Store' -x '__MACOSX'",
"post-deploy:push": "aws --profile=fortunoff-admin s3 cp public.zip s3://public-critical-editions-data/public.zip --acl public-read",
"post-deploy": "yarn post-deploy:zip && yarn post-deploy:push",

"fetch-public:curl": "curl --output public.zip https://public-critical-editions-data.s3.amazonaws.com/public.zip",
"fetch-public:unzip": "unzip public.zip",
"fetch-public:cleanup": "rm public.zip",
"fetch-public": "yarn fetch-public:curl && yarn fetch-public:unzip && yarn fetch-public:cleanup"
"fetch-public": "yarn fetch-public:curl && yarn fetch-public:unzip && yarn fetch-public:cleanup",

"publish-test-data:zip": "zip -r test-public.zip public -x '.DS_Store' -x '__MACOSX'",
"publish-test-data:push": "aws --profile=fortunoff-admin s3 cp test-public.zip s3://public-critical-editions-data/test-public.zip --acl public-read",
"publish-test-data": "yarn publish-test-data:zip && yarn publish-test-data:push",

"fetch-test-data:curl":"curl --output test-public.zip https://public-critical-editions-data.s3.amazonaws.com/test-public.zip ",
"fetch-test-data:unzip": "unzip test-public.zip ",
"fetch-test-data:cleanup": "rm test-public.zip ",
"fetch-test-data": "yarn fetch-test-data:curl && yarn fetch-test-data:unzip && yarn fetch-test-data:cleanup"
},
"eslintConfig": {
"extends": "react-app"
Expand Down
37 changes: 37 additions & 0 deletions scripts/compare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from hashlib import md5
import os
import glob


dirs = ["./build-2.1.0", "./build-2.0.0"]
base = dirs[0]
dir_b = dirs[1]
files = glob.glob(f"{base}/**", recursive=True)

def compare(fname, base_dir, dir_b):
match_part = fname.replace(base_dir, "")

# print(fname, "-", base_dir, "=", match_part)
# file_b = os.path.join(dir_b, match_part)
file_b = f"{dir_b}/{match_part}"

if not os.path.exists(file_b):
print(f"file not found: {file_b}")
return
# else:
# print(f"file found: {file_b}")
# print(fname, file_b)

if not os.path.isfile(fname):
return

left_hash = md5(open(fname, "rb").read()).hexdigest()
right_hash = md5(open(file_b, "rb").read()).hexdigest()

if left_hash == right_hash:
print(f"files match {fname} {file_b}")
else:
print(f"files don't match: {fname} {file_b}")

for file in files:
compare(file,base, dir_b)
15 changes: 13 additions & 2 deletions src/CriticalEditionData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface HeaderBlockData {
}

export interface ParagraphBlockData extends BlockData {
paragraphType: 'blockquote' | 'paragraph';
paragraphType: 'blockquote' | 'paragraph' | 'embed';
id?: string;
text: string;
}
Expand All @@ -22,12 +22,23 @@ export interface FootnoteParagraphBlockData extends ParagraphBlockData {
label: string;
}

export interface ImageBlockData extends BlockData {
export interface ImageBlockData extends InlineEmbedBlockData {
src: string;
srcset?: string;
sizes?: string;
}

export interface AviaryVideoBlockData extends InlineEmbedBlockData {
ead_id: string;
tape: string;
start_time: number;
end_time: number;
}

export interface InlineEmbedBlockData extends BlockData {
caption?: string;
}

export interface CriticalEditionDocument {
version?: number;
time?: number;
Expand Down
19 changes: 19 additions & 0 deletions src/CriticalEditionData/validators/validAviaryVideoBlockData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { AviaryVideoBlockData } from '..';
import DebugLogger from '../../utils/DebugLogger';
import ValidatorFunction from './ValidatorFunction';

const logger = new DebugLogger('validImageBlockData').hush();
const validAviaryVideoBlockData: ValidatorFunction<AviaryVideoBlockData> = (data: any) => {

logger.log('Validating video data ', data);
logger.warn('Video data validation not implemented');
// TODO - make sure there's a src at least

// if (data.embedCode && !(typeof data.embedCode === "string")) { throw new Error("FootnoteParagraphBlockData requires .embedCode to be undefined or String") }
// if (!data.id || !(typeof data.id === "string")) { throw new Error("FootnoteParagraphBlockData requires .id String") }
// if (!data.label || !(typeof data.label === "string")) { throw new Error("FootnoteParagraphBlockData requires .label String") }

return data as AviaryVideoBlockData;
};

export default validAviaryVideoBlockData;
18 changes: 12 additions & 6 deletions src/CriticalEditionData/validators/validBlockData.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { AviaryVideoBlock } from 'components/Viewer/ContentBody/Block/AviaryVideoBlock';
import { CriticalEditionDocumentBlock } from '..';
import DebugLogger from '../../utils/DebugLogger';
import ValidatorFunction from './ValidatorFunction';
import validFootnoteParagraphBlockData from './validFootnoteParagraphBlockData';
import validImageBlockData from './validImageBlockData';
import validParagraphBlockData from './validParagraphBlockData';
import validAviaryVideoBlockData from './validAviaryVideoBlockData';

const logger = new DebugLogger('validBlockData').hush();
const logger = new DebugLogger('validBlockData') //.hush();

const validBlockData: ValidatorFunction<CriticalEditionDocumentBlock> = (
data: any
) => {
logger.log('Validating block', data);

if (!data) {
throw new Error('No object provided');
Expand All @@ -23,14 +24,19 @@ const validBlockData: ValidatorFunction<CriticalEditionDocumentBlock> = (
throw new Error('Block requires field .data of type Object');
}


const blockType = data.type.toLowerCase()
// validate the data
if (data.type.toLowerCase().trim() === 'paragraph') {
if (blockType == 'paragraph') {
validParagraphBlockData(data.data);
} else if (data.type.toLowerCase().trim() === 'footnoteparagraph') {
} else if (blockType == 'footnoteparagraph') {
validFootnoteParagraphBlockData(data.data);
} else if (data.type.toLowerCase().trim() === 'image') {
} else if (blockType == 'image') {
validImageBlockData(data.data);
} else {
} else if (blockType == 'aviary') {
validAviaryVideoBlockData(data.data);
}
else {
throw new Error(`Unsupported block type: ${data.type}`);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.Aviary {
width: 100%;
/* use width as a way to constrain the height, which is
determined using padding in the AviaryIframeContainer
defined below */
max-width: 150vh;
}

.AviaryIframeContainer {
background-color: lightgray;
padding:56.25% 0 0 0;
position:relative;
overflow: hidden;
width: 100%;
}

.Aviary iframe {
position:absolute;
top:0;
left:0;
bottom: 0;
right: 0;
width:100%;
height:100%;
}
30 changes: 30 additions & 0 deletions src/components/Viewer/ContentBody/Block/AviaryVideoBlock/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { AviaryVideoBlockData } from '../../../../../CriticalEditionData';
import { InlineEmbed } from '../InlineEmbed';
import styles from './AviaryVideoBlock.module.css';

export interface AviaryVideoBlockProps {
data: AviaryVideoBlockData
}

export function AviaryVideoBlock(props: AviaryVideoBlockProps) {
const {
data: { ead_id, tape, start_time, end_time, caption },
} = props;

const component = (<div className={styles.Aviary}>
<div className={styles.AviaryIframeContainer}>
<iframe src={`https://fortunoff.aviaryplatform.com/c/${ead_id}/${tape}/?t=${start_time}&e=${end_time}&embed=true&media_file=true`} allow="fullscreen" frameborder="0"></iframe>
</div>
</div>)

console.log("Rendering video block", props.data)

return (
<InlineEmbed
embedComponent={component}
data={{caption}}
/>
)

}
1 change: 1 addition & 0 deletions src/components/Viewer/ContentBody/Block/Block.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
border-left: 0px solid transparent;
/* padding-left: 10px; */
/* padding-left: 20px; */
width: 100%;
}
.LeftMargin,
.RightMargin {
Expand Down
18 changes: 2 additions & 16 deletions src/components/Viewer/ContentBody/Block/Image/Image.module.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
.Image {
font-size: 14px;

padding: 10px;
/* border: 1px solid #333; */
/* box-shadow: 0px 0px 10px #ddd; */
display: flex;
justify-content: center;
}

.Image img {
Expand All @@ -14,14 +11,3 @@
overflow: hidden;
}

.ImgContainer {
display: flex;
justify-content: center;
}

.Caption {
margin-top: 13px;
font-size: 15px;
line-height: 2em;
color: #333;
}
20 changes: 10 additions & 10 deletions src/components/Viewer/ContentBody/Block/Image/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import React from 'react';
import { ImageBlockData } from '../../../../../CriticalEditionData';
import { InlineEmbed } from '../InlineEmbed';
import styles from './Image.module.css';

export interface ImageProps {
data: ImageBlockData;
}

export function Image(props: ImageProps) {
const {
data: { src, srcset, sizes, caption },
} = props;

const component = (<div className={styles.Image}>
<img srcSet={srcset} sizes={sizes} src={src} alt={caption || ''} />
</div>)
return (
<div className={`sans-copy-ff ${styles.Image}`}>
<div className={styles.ImgContainer}>
<img srcSet={srcset} sizes={sizes} src={src} alt={caption || ''} />
</div>
<div
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: caption || '' }}
className={styles.Caption}
<InlineEmbed
embedComponent={component}
data={{caption}}
/>
</div>
);
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.InlineEmbed {
padding: 10px;
}

.InlineEmbed {
max-width: 100%;
height: 100%;
overflow: hidden;
}

.EmbedContainer {
display: flex;
justify-content: center;
}

.Caption {
margin-top: 13px;
font-size: 15px;
line-height: 2em;
color: #333;
}
28 changes: 28 additions & 0 deletions src/components/Viewer/ContentBody/Block/InlineEmbed/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { ComponentType } from 'react';
import { InlineEmbedBlockData } from '../../../../../CriticalEditionData';
import styles from './InlineEmbed.module.css';

export interface InlineEmbedProps {
data: InlineEmbedBlockData
embedComponent: JSX.Element
}

export function InlineEmbed(props: InlineEmbedProps) {
const {
embedComponent: EmbedComponent,
data: { caption },
} = props;

return (
<div className={`sans-copy-ff ${styles.InlineEmbed}`}>
<div className={styles.EmbedContainer}>
{EmbedComponent}
</div>
<div
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: caption || '' }}
className={styles.Caption}
/>
</div>
);
}
Loading

0 comments on commit a71baf5

Please sign in to comment.