Skip to content
This repository was archived by the owner on Feb 6, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
### Others

- cli: v2.1.1 ([CHANGELOG](https://github.com/deckgo/deckdeckgo/blob/master/cli/CHANGELOG.md))
- cloud: v2.0.0 ([CHANGELOG](https://github.com/deckgo/deckdeckgo/blob/master/cloud/CHANGELOG.md))
- cloud: v2.1.0 ([CHANGELOG](https://github.com/deckgo/deckdeckgo/blob/master/cloud/CHANGELOG.md))
- deck-utils: v3.3.1 ([CHANGELOG](https://github.com/deckgo/deckdeckgo/blob/master/utils/deck/CHANGELOG.md))
- kit: v2.0.3 ([CHANGELOG](https://github.com/deckgo/deckdeckgo/blob/master/kit/CHANGELOG.md))
- starter kit: v7.1.4 ([CHANGELOG](https://github.com/deckgo/starter-kit/blob/master/CHANGELOG.md))
Expand Down
6 changes: 6 additions & 0 deletions cloud/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<a name="2.1.0"></a>

# 2.1.0 (2021-01-31)

- publish templates to API

<a name="2.0.0"></a>

# 2.0.0 (2021-01-29)
Expand Down
5 changes: 2 additions & 3 deletions cloud/functions/.gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
## Compiled JavaScript files
**/*.js
**/*.js.map
lib/

# Typescript v1 declaration files
typings/

node_modules/
node_modules/
2 changes: 1 addition & 1 deletion cloud/functions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion cloud/functions/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"name": "functions",
"version": "2.0.0",
"version": "2.1.0",
"scripts": {
"prebuild": "node ./scripts/copy-templates.js",
"lint": "tslint --project tsconfig.json",
"build": "tsc",
"serve": "npm run build && firebase serve --only functions",
Expand Down
5 changes: 5 additions & 0 deletions cloud/functions/scripts/copy-templates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env node

const fs = require('fs');

fs.copyFileSync('../../studio/src/assets/templates.json', './src/assets/templates.json');
44 changes: 44 additions & 0 deletions cloud/functions/src/assets/templates.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"community": [
{
"id": "db8abf75-5372-41be-8ee6-799b4884882c",
"data": {
"tag": "deckgo-slide-countdown",
"author": {
"name": "Gaurav Mahto",
"url": "https://github.com/gauravmahto"
},
"cdn": "https://unpkg.com/@deckdeckgo/slide-countdown@latest/dist/deckdeckgo-slide-countdown/deckdeckgo-slide-countdown.esm.js",
"props": [
{
"name": "days",
"type": "number",
"placeholder": "The amount of days before your presentations"
},
{
"name": "hours",
"type": "number",
"placeholder": "The amount of hours before your presentations (max. 23)"
},
{
"name": "minutes",
"type": "number",
"placeholder": "The amount of minutes before your presentations (max. 59)"
},
{
"name": "until",
"type": "string",
"placeholder": "A specific date and time until when your presentation will start (format: 2021-08-27T23:25:59.000+02:00)"
}
],
"slots": [
{
"name": "title",
"placeholder": "Display the remaining time until your presentation",
"types": ["h1", "h2", "h3", "section"]
}
]
}
}
]
}
2 changes: 1 addition & 1 deletion cloud/functions/src/model/api/api.slide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import {SlideAttributes, SlideTemplate} from '../data/slide';

export interface ApiSlide {
content?: string;
template: SlideTemplate;
template: SlideTemplate | string;
attributes?: SlideAttributes;
}
46 changes: 8 additions & 38 deletions cloud/functions/src/model/data/slide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,22 @@ export enum SlideTemplate {
PLAYGROUND = 'playground',
}

export enum SlideChartType {
LINE = 'line',
PIE = 'pie',
BAR = 'bar',
}

export enum SlideSplitType {
export enum SlideScope {
DEFAULT = 'default',
DEMO = 'demo',
COMMUNITY = 'community',
USER = 'user',
}

export type SlideAttributesYAxisDomain = 'max' | 'extent';

export interface SlideAttributes {
style?: string;
src?: string;
customBackground?: string;
imgSrc?: string;
imgAlt?: string;

content?: string;
customQRCode?: boolean;

type?: SlideChartType | SlideSplitType;
innerRadius?: number;
animation?: boolean;
datePattern?: string;
yAxisDomain?: SlideAttributesYAxisDomain;
smooth?: boolean;
area?: boolean;
ticks?: number;
grid?: boolean;
separator?: string;

vertical?: boolean;

imgMode?: string;

customLoader?: boolean;

theme?: string;
[key: string]: string | number | boolean;
}

export interface SlideData {
content?: string;
template: SlideTemplate;

template: SlideTemplate | string;
scope?: SlideScope;

attributes?: SlideAttributes;

api_id?: string;
Expand Down
37 changes: 37 additions & 0 deletions cloud/functions/src/model/data/template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {firestore} from 'firebase-admin';

export interface TemplateDataSlot {
name: string;
placeholder?: string;
types?: string[];
}

export interface TemplateDataProp {
name: string;
type: 'string' | 'number' | 'boolean';
placeholder?: string;
}

export interface TemplateDataAuthor {
name: string;
url?: string;
}

export interface TemplateData {
owner_id: string;

tag: string;
cdn?: string;
author?: TemplateDataAuthor;
slots?: TemplateDataSlot[];
props?: TemplateDataProp[];

created_at?: firestore.Timestamp;
updated_at?: firestore.Timestamp;
}

export interface Template {
id: string;
ref: firestore.DocumentReference;
data: TemplateData;
}
58 changes: 47 additions & 11 deletions cloud/functions/src/request/utils/convert-deck-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@ import {Deck} from '../../model/data/deck';
import {ApiDeck, ApiDeckAttributes} from '../../model/api/api.deck';
import {ApiSlide} from '../../model/api/api.slide';
import {Slide, SlideAttributes, SlideTemplate} from '../../model/data/slide';
import {Template} from '../../model/data/template';

import {findSlide} from '../../utils/data/slide-utils';
import {getGoogleFontScript} from './google-fonts-utils';
import {findTemplates, getTemplate} from '../../utils/data/template-utils';

interface SlideAndTemplate {
apiSlide: ApiSlide;
template: Template | undefined;
}

export function convertDeck(deck: Deck): Promise<ApiDeck> {
return new Promise<ApiDeck>(async (resolve, reject) => {
try {
const apiSlides: ApiSlide[] = await convertSlides(deck);
const apiSlides: SlideAndTemplate[] = await convertSlides(deck);

const apiDeck: ApiDeck = {
name: deck.data.name ? deck.data.name.trim() : deck.data.name,
Expand All @@ -23,14 +30,20 @@ export function convertDeck(deck: Deck): Promise<ApiDeck> {
background: deck.data.background,
header: deck.data.header,
footer: deck.data.footer,
slides: apiSlides,
slides: apiSlides.map((slideAndTemplate: SlideAndTemplate) => slideAndTemplate.apiSlide),
};

const googleFontScript: string | undefined = await getGoogleFontScript(deck);
if (googleFontScript !== undefined) {
apiDeck.head_extra = googleFontScript;
}

const scripts: string | undefined = getTemplateScripts(apiSlides);

if (scripts !== undefined) {
apiDeck.head_extra = apiDeck.head_extra !== undefined ? `${apiDeck.head_extra}${scripts}` : scripts;
}

const attributes: ApiDeckAttributes | undefined = await convertDeckAttributes(deck);
if (attributes !== undefined) {
apiDeck.attributes = attributes;
Expand Down Expand Up @@ -73,28 +86,30 @@ async function convertDeckAttributes(deck: Deck): Promise<ApiDeckAttributes | un
return attributes;
}

function convertSlides(deck: Deck): Promise<ApiSlide[]> {
return new Promise<ApiSlide[]>(async (resolve, reject) => {
function convertSlides(deck: Deck): Promise<SlideAndTemplate[]> {
return new Promise<SlideAndTemplate[]>(async (resolve, reject) => {
if (!deck.data.slides || deck.data.slides.length <= 0) {
resolve([]);
return;
}

try {
const promises: Promise<ApiSlide>[] = [];
const templates: Template[] = await findTemplates(deck.data.owner_id);

const promises: Promise<SlideAndTemplate>[] = [];

for (let i: number = 0; i < deck.data.slides.length; i++) {
const slideId: string = deck.data.slides[i];

promises.push(convertSlide(deck, slideId));
promises.push(convertSlide(deck, templates, slideId));
}

if (!promises || promises.length <= 0) {
resolve([]);
return;
}

const slides: ApiSlide[] = await Promise.all(promises);
const slides: SlideAndTemplate[] = await Promise.all(promises);

resolve(slides);
} catch (err) {
Expand All @@ -103,8 +118,8 @@ function convertSlides(deck: Deck): Promise<ApiSlide[]> {
});
}

function convertSlide(deck: Deck, slideId: string): Promise<ApiSlide> {
return new Promise<ApiSlide>(async (resolve, reject) => {
function convertSlide(deck: Deck, templates: Template[], slideId: string): Promise<SlideAndTemplate> {
return new Promise<SlideAndTemplate>(async (resolve, reject) => {
const slide: Slide = await findSlide(deck.id, slideId);

if (!slide || !slide.data) {
Expand All @@ -114,16 +129,24 @@ function convertSlide(deck: Deck, slideId: string): Promise<ApiSlide> {

const attributes: SlideAttributes | undefined = await convertAttributesToString(slide.data.attributes);

const slideTemplate: SlideTemplate | undefined = SlideTemplate[slide.data.template.toUpperCase() as keyof typeof SlideTemplate];
const slideTag: string = slideTemplate ? `deckgo-slide-${slideTemplate.toLowerCase()}` : slide.data.template;

const apiSlide: ApiSlide = {
template: slide.data.template,
template: slideTag,
content: slide.data.content,
attributes: attributes,
};

const cleanApiSlide: ApiSlide = await convertSlideQRCode(apiSlide);
cleanApiSlide.content = await cleanNotes(apiSlide.content);

resolve(cleanApiSlide);
const template: Template | undefined = await getTemplate(templates, slide.data.scope, slide.data.template);

resolve({
apiSlide: cleanApiSlide,
template,
});
});
}

Expand Down Expand Up @@ -197,3 +220,16 @@ function convertSlideQRCode(apiSlide: ApiSlide): Promise<ApiSlide> {
resolve(apiSlide);
});
}

function getTemplateScripts(apiSlides: SlideAndTemplate[]) {
const cdns: string[] | undefined = apiSlides
.filter((slideAndTemplate: SlideAndTemplate) => slideAndTemplate.template !== undefined && slideAndTemplate.template.data.cdn !== undefined)
.map((slideAndTemplate: SlideAndTemplate) => (slideAndTemplate.template as Template).data.cdn as string);

if (cdns !== undefined && cdns.length > 0) {
const uniqueCdns: string[] = [...new Set(cdns)];
return uniqueCdns.map((cdn: string) => `<script type="module" src="${cdn}" />`).join();
}

return undefined;
}
44 changes: 44 additions & 0 deletions cloud/functions/src/utils/data/template-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as admin from 'firebase-admin';

import {Template} from '../../model/data/template';
import {SlideScope} from '../../model/data/slide';

import * as communityTemplates from '../../assets/templates.json';

export function findTemplates(ownerId: string): Promise<Template[]> {
return new Promise<Template[]>(async (resolve, reject) => {
try {
const snapshot: admin.firestore.QuerySnapshot = await admin.firestore().collection('templates').where('owner_id', '==', ownerId).get();

if (!snapshot || !snapshot.docs) {
resolve([]);
return;
}

const templates: Template[] = snapshot.docs.map((doc) => {
const id = doc.id;
const ref = doc.ref;

return {
id: id,
ref: ref,
data: doc.data(),
} as Template;
});

resolve(templates);
} catch (err) {
reject(err);
}
});
}

export async function getTemplate(userTemplates: Template[], scope: SlideScope | undefined, template: string): Promise<Template | undefined> {
if (!scope || scope === SlideScope.DEFAULT) {
return undefined;
}

const templates: Template[] = scope === SlideScope.COMMUNITY ? (communityTemplates.community as Template[]) : userTemplates;

return templates.find((filteredTemplate: Template) => filteredTemplate.data.tag === template);
}
Loading