update
This commit is contained in:
parent
666943d4f1
commit
51208cad8d
27 changed files with 1003 additions and 678 deletions
13
src/app.ts
13
src/app.ts
|
|
@ -12,6 +12,7 @@ import AdminAuthMiddleware from './middlewares/AdminAuthMiddleware'
|
|||
import DelegateAuthMiddleware from './middlewares/DelegateAuthMiddleware'
|
||||
import PublicController from './controllers/PublicController'
|
||||
import cors from 'cors'
|
||||
import twig from 'twig'
|
||||
|
||||
dotenv.config({
|
||||
path: __dirname + '/../.env'
|
||||
|
|
@ -21,6 +22,8 @@ const app: express.Application = express()
|
|||
const host: string = "0.0.0.0"
|
||||
const port: number = 8001
|
||||
|
||||
twig.cache(false)
|
||||
|
||||
let main = async () => {
|
||||
mongoose.connection.on('error', err => {
|
||||
console.error(err)
|
||||
|
|
@ -36,6 +39,10 @@ let main = async () => {
|
|||
console.log('> Connected to mongodb')
|
||||
})
|
||||
|
||||
app.set("twig options", {
|
||||
allow_async: true,
|
||||
strict_variables: false
|
||||
})
|
||||
app.use(cors())
|
||||
app.use(bodyParser.json())
|
||||
|
||||
|
|
@ -46,6 +53,8 @@ let main = async () => {
|
|||
|
||||
app.get('/', PublicController.home)
|
||||
app.get('/association/:slug', PublicController.organization)
|
||||
app.get('/a-propos', PublicController.about)
|
||||
app.get('/mentions-legales', PublicController.legals)
|
||||
|
||||
app.get('/icon/:id', DefaultController.viewIcon)
|
||||
app.get('/email', DefaultController.sendEmail)
|
||||
|
|
@ -79,6 +88,8 @@ let main = async () => {
|
|||
.put('/', DelegateController.update)
|
||||
.post('/submit', DelegateController.submit)
|
||||
.post('/thumbnail', DelegateController.uploadThumbnail())
|
||||
.post('/cover', DelegateController.uploadCover())
|
||||
.post('/medias', DelegateController.uploadMedias())
|
||||
.delete('/', DelegateController.destroy)
|
||||
)
|
||||
|
||||
|
|
@ -92,7 +103,7 @@ let main = async () => {
|
|||
*/
|
||||
|
||||
app.post('/api/media', MediaController.uploadRoute())
|
||||
app.delete('/api/media/:key', MediaController.delete)
|
||||
//app.delete('/api/media/:key', MediaController.delete)
|
||||
|
||||
app.use(express.static('/apps/forum_server/static'))
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import cryptoRandomString from 'crypto-random-string'
|
|||
import EmailService from '../EmailService'
|
||||
import slugify from 'slugify'
|
||||
import { Document } from 'mongoose'
|
||||
import MediaService from '../MediaService'
|
||||
|
||||
export default class AdminOrganizationController {
|
||||
static getMany(req: express.Request, res: express.Response) {
|
||||
|
|
@ -22,22 +23,22 @@ export default class AdminOrganizationController {
|
|||
let body: any = {
|
||||
token: AdminOrganizationController.generateToken(),
|
||||
createdAt: new Date(),
|
||||
slug: req.body.adminName === undefined ? undefined : slugify(req.body.adminName).toLowerCase(),
|
||||
...req.body
|
||||
// ...{
|
||||
// proposedVersion: {
|
||||
// name: '',
|
||||
// descriptionShort: '',
|
||||
// descriptionLong: '',
|
||||
// contacts: [],
|
||||
// schedule: [],
|
||||
// pricing: [],
|
||||
// tag: null,
|
||||
// cover: null,
|
||||
// gallery: [],
|
||||
// thumbnail: null
|
||||
// }
|
||||
// }
|
||||
slug: slugify(req.body.adminName).toLowerCase(),
|
||||
...req.body,
|
||||
...{
|
||||
proposedVersion: {
|
||||
name: req.body.adminName
|
||||
// descriptionShort: '',
|
||||
// descriptionLong: '',
|
||||
// contacts: [],
|
||||
// schedule: [],
|
||||
// pricing: [],
|
||||
// tag: null,
|
||||
// cover: null,
|
||||
// gallery: [],
|
||||
// thumbnail: null
|
||||
}
|
||||
}
|
||||
}
|
||||
Organization.create(body).then(data => {
|
||||
AdminOrganizationController.sendEmailTokenUniversal(data)
|
||||
|
|
@ -75,16 +76,46 @@ export default class AdminOrganizationController {
|
|||
}
|
||||
|
||||
static destroy(req: express.Request, res: express.Response) {
|
||||
Organization.deleteOne({ _id: req.params.id }).then(data => {
|
||||
let isSuccess = data.deletedCount !== undefined && data.deletedCount > 0
|
||||
res.status(isSuccess ? 200 : 400).json({
|
||||
success: isSuccess,
|
||||
data
|
||||
})
|
||||
}).catch(err => res.status(400).json({
|
||||
success: false,
|
||||
errors: err.errors
|
||||
}))
|
||||
Organization.findById(req.params.id).then(organization => {
|
||||
Organization.deleteOne({ _id: req.params.id }).then(data => {
|
||||
if (organization === null) {
|
||||
return
|
||||
}
|
||||
// delete all media from this organization
|
||||
let keys: string[] = []
|
||||
const proposedVersion: any = organization.get('proposedVersion')
|
||||
if (proposedVersion.thumbnail !== undefined && proposedVersion.thumbnail !== null) {
|
||||
keys.push(proposedVersion.thumbnail.key)
|
||||
}
|
||||
if (proposedVersion.cover !== undefined && proposedVersion.cover !== null) {
|
||||
keys.push(proposedVersion.cover.key)
|
||||
}
|
||||
console.log(proposedVersion.gallery)
|
||||
if (Array.isArray(proposedVersion.gallery)) {
|
||||
keys = keys.concat(proposedVersion.gallery.map((m: any) => m.key))
|
||||
}
|
||||
|
||||
keys.forEach((key: string) => {
|
||||
if (key === undefined || key === null || key.length <= 2) { return }
|
||||
console.log('> OrganizationDestroyMediaCleanup: Deleted ' + key)
|
||||
MediaService.getS3().deleteObject({
|
||||
Bucket: MediaService.getBucket(),
|
||||
Key: key
|
||||
}, (err, _) => {
|
||||
if (err !== null) {
|
||||
console.error('> OrganizationDestroyMediaCleanup: Cannot delete a media from a organization which will be deleted')
|
||||
console.log(err, err.stack)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
let isSuccess = data.deletedCount !== undefined && data.deletedCount > 0
|
||||
res.status(isSuccess ? 200 : 400).json({
|
||||
success: isSuccess,
|
||||
data
|
||||
})
|
||||
}).catch(err => res.status(400).json({ success: false, errors: err.errors }))
|
||||
}).catch(err => res.status(400).json({ success: false, errors: err }))
|
||||
}
|
||||
|
||||
static sendEmailToken(req: express.Request, res: express.Response) {
|
||||
|
|
@ -150,11 +181,16 @@ export default class AdminOrganizationController {
|
|||
}
|
||||
|
||||
static sendEmailTokenUniversal(data: Document) {
|
||||
const baseUrl = process.env.WEB_UI_URL === undefined ? "URL_NOT_FOUND" : process.env.WEB_UI_URL
|
||||
EmailService.send(
|
||||
data.get('email'),
|
||||
"Votre lien secret pour modifier votre association",
|
||||
"token",
|
||||
{ adminName: data.get('adminName'), token: data.get('token') }
|
||||
{
|
||||
adminName: data.get('adminName'),
|
||||
token: data.get('token'),
|
||||
link: baseUrl + '/delegate?delegateToken=' + data.get('token')
|
||||
}
|
||||
).then(() => {
|
||||
console.log('> A token email was sent')
|
||||
}).catch(() => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import Tag from '../models/Tag'
|
||||
import Organization from '../models/Organization'
|
||||
import * as express from 'express'
|
||||
import EmailService from '../EmailService'
|
||||
|
|
@ -9,7 +10,15 @@ import slugify from 'slugify'
|
|||
export default class DelegateController {
|
||||
|
||||
static get(req: express.Request, res: express.Response) {
|
||||
res.json({ success: true, data: res.locals.organization })
|
||||
Tag.find().then(tags => {
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
organization: res.locals.organization,
|
||||
tags
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
static test(req: express.Request, res: express.Response) {
|
||||
|
|
@ -17,28 +26,92 @@ export default class DelegateController {
|
|||
}
|
||||
|
||||
static update(req: express.Request, res: express.Response) {
|
||||
if (res.locals.organization.validationState === 'pending') {
|
||||
const organization: any = res.locals.organization
|
||||
if (organization.validationState === 'pending') {
|
||||
return res.json({
|
||||
success: false,
|
||||
errors: [{ code: 'update-forbidden', message: 'Organization cannot be updated while the validationState is set to "pending"' }]
|
||||
})
|
||||
}
|
||||
// only update proposedVersion
|
||||
Organization.updateOne({ _id: res.locals.organization._id }, {
|
||||
proposedVersion: req.body,
|
||||
updatedAt: new Date()
|
||||
}).then(data => {
|
||||
res.json({
|
||||
success: true,
|
||||
data,
|
||||
body: req.body
|
||||
|
||||
const next = (tag: any) => {
|
||||
// only update proposedVersion
|
||||
let proposedVersion: any = req.body
|
||||
proposedVersion.tag = tag
|
||||
proposedVersion.descriptionLong = proposedVersion.descriptionLong.replace(/\n/g, '')
|
||||
|
||||
// validate contact.address
|
||||
// validate all fields to not overflow
|
||||
// validate the size of all the json, all the data recorded
|
||||
|
||||
// manage medias
|
||||
// delete media that are not used
|
||||
if (!Array.isArray(proposedVersion.gallery)) {
|
||||
proposedVersion.gallery = []
|
||||
}
|
||||
if (Array.isArray(organization.proposedVersion.gallery)) {
|
||||
organization.proposedVersion.gallery.forEach((media: any) => {
|
||||
// if a existing media is not in the new version we delete it
|
||||
if (proposedVersion.gallery.filter((m: any) => m.key === media.key).length === 0) {
|
||||
console.log('> Old media cleanup: we must delete ', media)
|
||||
MediaService.getS3().deleteObject({
|
||||
Bucket: MediaService.getBucket(),
|
||||
Key: media.key
|
||||
}, (err, _) => {
|
||||
if (err !== null) {
|
||||
console.error('> Cannot delete a old media element')
|
||||
console.log(err, err.stack)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// format schedule, pricing
|
||||
if (!Array.isArray(proposedVersion.schedule)) {
|
||||
proposedVersion.schedule = []
|
||||
}
|
||||
if (!Array.isArray(proposedVersion.pricing)) {
|
||||
proposedVersion.pricing = []
|
||||
}
|
||||
|
||||
Organization.updateOne({ _id: organization._id }, {
|
||||
proposedVersion,
|
||||
updatedAt: new Date()
|
||||
}).then(data => {
|
||||
res.json({
|
||||
success: true,
|
||||
data,
|
||||
body: req.body
|
||||
})
|
||||
}).catch(err => {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
errors: err.errors !== undefined ? err.errors : err
|
||||
})
|
||||
})
|
||||
}).catch(err => {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
errors: err.errors !== undefined ? err.errors : err
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (req.body.tag !== undefined && req.body.tag !== null && req.body.tag.length > 2) {
|
||||
// skip the tag part if the tag didn't changed
|
||||
if (
|
||||
organization.proposedVersion.tag === undefined ||
|
||||
organization.proposedVersion.tag === null ||
|
||||
req.body.tag !== organization.proposedVersion.tag._id
|
||||
) {
|
||||
// if the tag is defined, search the tag id
|
||||
Tag.findById(req.body.tag).then(tag => {
|
||||
next(tag)
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
res.status(400).json({ success: false, errors: err, _note: 'The tag id provided is invalid' })
|
||||
})
|
||||
} else {
|
||||
next(organization.tag)
|
||||
}
|
||||
} else {
|
||||
next(null)
|
||||
}
|
||||
}
|
||||
|
||||
static submit(req: express.Request, res: express.Response) {
|
||||
|
|
@ -78,7 +151,6 @@ export default class DelegateController {
|
|||
}
|
||||
|
||||
static uploadThumbnail(): express.RequestHandler[] {
|
||||
// we upload the thumbnail
|
||||
return [
|
||||
multer({
|
||||
storage: multerS3({
|
||||
|
|
@ -88,14 +160,14 @@ export default class DelegateController {
|
|||
contentType: multerS3.AUTO_CONTENT_TYPE,
|
||||
key: (_: any, file: any, cb: any) => {
|
||||
console.log(file)
|
||||
cb(null, Date.now().toString() + '_' + slugify(file.originalname))
|
||||
cb(null, Date.now().toString() + '_thumbnail')
|
||||
}
|
||||
})
|
||||
}).single('file'),
|
||||
(req: express.Request, res: express.Response) => {
|
||||
// if the current thumbnail is defined AND the published thumnbnail is defined AND the current thumbnail is different from the published one
|
||||
// THEN we delete the current thumbnail
|
||||
const proposedVersion: any = res.locals.organization.proposedVersion
|
||||
let proposedVersion: any = res.locals.organization.proposedVersion
|
||||
const publishedVersion: any = res.locals.organization.publishedVersion
|
||||
if (
|
||||
proposedVersion !== undefined && proposedVersion !== null &&
|
||||
|
|
@ -109,7 +181,7 @@ export default class DelegateController {
|
|||
Bucket: MediaService.getBucket(),
|
||||
Key: proposedVersion.thumbnail.key
|
||||
}, (err, _) => {
|
||||
if (err !== null) {
|
||||
if (err !== null) {
|
||||
console.error('> Cannot delete a old thumbnail')
|
||||
console.log(err, err.stack)
|
||||
}
|
||||
|
|
@ -122,13 +194,134 @@ export default class DelegateController {
|
|||
contentType: req.file.contentType,
|
||||
// @ts-ignore
|
||||
location: req.file.location,
|
||||
// @ts-ignore
|
||||
size: req.file.size,
|
||||
// @ts-ignore
|
||||
originalFileName: req.file.originalname,
|
||||
type: 'thumbnail'
|
||||
}
|
||||
proposedVersion = { ...res.locals.organization.proposedVersion, thumbnail }
|
||||
Organization.updateOne({ _id: res.locals.organization._id }, {
|
||||
proposedVersion: { thumbnail },
|
||||
proposedVersion,
|
||||
updatedAt: new Date()
|
||||
}).then(data => {
|
||||
res.json({ success: true, data, thumbnail })
|
||||
res.json({ success: true, data, thumbnail, proposedVersion })
|
||||
}).catch(err => {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
errors: err.errors !== undefined ? err.errors : err
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
static uploadCover(): express.RequestHandler[] {
|
||||
return [
|
||||
multer({
|
||||
storage: multerS3({
|
||||
s3: MediaService.getS3(),
|
||||
bucket: 'development-bucket',
|
||||
acl: 'public-read',
|
||||
contentType: multerS3.AUTO_CONTENT_TYPE,
|
||||
key: (_: any, file: any, cb: any) => {
|
||||
console.log(file)
|
||||
cb(null, Date.now().toString() + '_cover')
|
||||
}
|
||||
})
|
||||
}).single('file'),
|
||||
(req: express.Request, res: express.Response) => {
|
||||
// if the current thumbnail is defined AND the published thumnbnail is defined AND the current thumbnail is different from the published one
|
||||
// THEN we delete the current thumbnail
|
||||
let proposedVersion: any = res.locals.organization.proposedVersion
|
||||
const publishedVersion: any = res.locals.organization.publishedVersion
|
||||
if (
|
||||
proposedVersion !== undefined && proposedVersion !== null &&
|
||||
proposedVersion.cover !== undefined && proposedVersion.cover !== null &&
|
||||
publishedVersion !== undefined && publishedVersion !== null &&
|
||||
publishedVersion.cover !== undefined && publishedVersion.cover !== null &&
|
||||
publishedVersion.cover.location !== proposedVersion.cover.location
|
||||
) {
|
||||
console.log(' we must delete ', proposedVersion.cover)
|
||||
MediaService.getS3().deleteObject({
|
||||
Bucket: MediaService.getBucket(),
|
||||
Key: proposedVersion.cover.key
|
||||
}, (err, _) => {
|
||||
if (err !== null) {
|
||||
console.error('> Cannot delete a old cover')
|
||||
console.log(err, err.stack)
|
||||
}
|
||||
})
|
||||
}
|
||||
const cover: any = {
|
||||
// @ts-ignore
|
||||
key: req.file.key,
|
||||
// @ts-ignore
|
||||
contentType: req.file.contentType,
|
||||
// @ts-ignore
|
||||
location: req.file.location,
|
||||
// @ts-ignore
|
||||
size: req.file.size,
|
||||
// @ts-ignore
|
||||
originalFileName: req.file.originalname,
|
||||
type: 'cover'
|
||||
}
|
||||
proposedVersion = { ...res.locals.organization.proposedVersion, cover }
|
||||
Organization.updateOne({ _id: res.locals.organization._id }, {
|
||||
proposedVersion,
|
||||
updatedAt: new Date()
|
||||
}).then(data => {
|
||||
res.json({ success: true, data, cover, proposedVersion })
|
||||
}).catch(err => {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
errors: err.errors !== undefined ? err.errors : err
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
static uploadMedias(): express.RequestHandler[] {
|
||||
return [
|
||||
multer({
|
||||
storage: multerS3({
|
||||
s3: MediaService.getS3(),
|
||||
bucket: 'development-bucket',
|
||||
acl: 'public-read',
|
||||
contentType: multerS3.AUTO_CONTENT_TYPE,
|
||||
key: (_: any, file: any, cb: any) => {
|
||||
console.log(file)
|
||||
cb(null, Date.now().toString() + '_media')
|
||||
}
|
||||
})
|
||||
}).array('file'),
|
||||
(req: express.Request, res: express.Response) => {
|
||||
let proposedVersion: any = res.locals.organization.proposedVersion
|
||||
|
||||
// @ts-ignore
|
||||
req.files.forEach((file: any) => {
|
||||
proposedVersion.gallery.push({
|
||||
key: file.key,
|
||||
contentType: file.contentType,
|
||||
location: file.location,
|
||||
size: file.size,
|
||||
type: 'image',
|
||||
originalFileName: file.originalname
|
||||
})
|
||||
})
|
||||
|
||||
Organization.updateOne({ _id: res.locals.organization._id }, {
|
||||
proposedVersion,
|
||||
updatedAt: new Date()
|
||||
}).then(result => {
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
result,
|
||||
gallery: proposedVersion.gallery
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default class MediaController {
|
|||
contentType: multerS3.AUTO_CONTENT_TYPE,
|
||||
key: (_: any, file: any, cb: any) => {
|
||||
console.log(file)
|
||||
cb(null, Date.now().toString() + '_' + slugify(file.originalname)) //use Date.now() for unique file keys
|
||||
cb(null, Date.now().toString()) //use Date.now() for unique file keys
|
||||
}
|
||||
})
|
||||
}).single('file'),
|
||||
|
|
@ -25,9 +25,6 @@ export default class MediaController {
|
|||
}
|
||||
|
||||
static upload(req: express.Request, res: express.Response) {
|
||||
|
||||
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: { file: req.file }
|
||||
|
|
|
|||
|
|
@ -7,24 +7,78 @@ import Mustache from 'mustache'
|
|||
import fs from 'fs'
|
||||
import { IconService, IconInterface } from '../IconService'
|
||||
import IORedis from 'ioredis'
|
||||
import Tag from '../models/Tag'
|
||||
|
||||
export default class PublicController {
|
||||
|
||||
|
||||
static async home(req: express.Request, res: express.Response) {
|
||||
// let client: IORedis.Redis = RedisService.getClient()
|
||||
// await client.set('hello', 'world')
|
||||
// res.json({
|
||||
// data: await client.get('hello')
|
||||
// })
|
||||
res.render('home.twig', {
|
||||
message : "Hello World"
|
||||
Tag.find().then(tags => {
|
||||
Organization.find().then(organizations => {
|
||||
res.render('home.twig', {
|
||||
tags,
|
||||
tagsJSON: JSON.stringify(tags),
|
||||
organizationsJSON: JSON.stringify(organizations.map(o => {
|
||||
const version = o.get('proposedVersion')
|
||||
return {
|
||||
name: version.name,
|
||||
description: version.descriptionShort,
|
||||
thumbnail: version.thumbnail.location,
|
||||
tag: version.tag._id,
|
||||
slug: o.get('slug')
|
||||
}
|
||||
}))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
static async organization(req: express.Request, res: express.Response) {
|
||||
res.render('index.twig', {
|
||||
message : "Hello World"
|
||||
})
|
||||
Organization.find({ slug: req.params.slug }).then(data => {
|
||||
if (data.length === 0) {
|
||||
res.status(404).render('not-found.twig')
|
||||
} else {
|
||||
const version = data[0].get('proposedVersion')
|
||||
if (version.contacts !== null && version.contacts !== undefined) {
|
||||
if (typeof version.contacts.address === 'string') {
|
||||
version.contacts.address = version.contacts.address.split('\n')
|
||||
}
|
||||
if (typeof version.contacts.phone === 'string') {
|
||||
let phone = version.contacts.phone
|
||||
if (phone.indexOf('+33') === 0) {
|
||||
phone = '0' + phone.substr(3)
|
||||
}
|
||||
let phoneSplit = ''
|
||||
let partEnd = false
|
||||
for (var i = 0; i < phone.length; i++) {
|
||||
phoneSplit += phone.charAt(i)
|
||||
if (partEnd === true) {
|
||||
phoneSplit += ' '
|
||||
}
|
||||
partEnd = !partEnd
|
||||
}
|
||||
version.contacts.phoneInt = "+33" + phone.substr(1)
|
||||
version.contacts.phoneSplit = phoneSplit
|
||||
}
|
||||
}
|
||||
console.log(version)
|
||||
res.render('organization.twig', {
|
||||
layout: 'standalone',
|
||||
data: version
|
||||
})
|
||||
}
|
||||
}).catch(_ => res.status(404).render('not-found.twig'))
|
||||
}
|
||||
|
||||
static async about(req: express.Request, res: express.Response) {
|
||||
res.render('about.twig')
|
||||
}
|
||||
|
||||
static async legals(req: express.Request, res: express.Response) {
|
||||
res.render('legals.twig')
|
||||
}
|
||||
}
|
||||
|
|
@ -29,11 +29,6 @@ class AllowedString extends mongoose.SchemaType {
|
|||
// @ts-ignore
|
||||
mongoose.Schema.Types['AllowedString'] = AllowedString
|
||||
|
||||
const ScheduleIntervalBoundary = {
|
||||
hour: { type: Number },
|
||||
minute: { type: Number }
|
||||
}
|
||||
|
||||
const Media = {
|
||||
location: { type: String },
|
||||
type: {
|
||||
|
|
@ -41,8 +36,10 @@ const Media = {
|
|||
name: 'MediaType',
|
||||
allowedValues: ['cover', 'thumbnail', 'video', 'image']
|
||||
},
|
||||
originalFileName: { type: String },
|
||||
key: { type: String },
|
||||
contentType: { type: String }
|
||||
contentType: { type: String },
|
||||
size: { type: Number } // size of the file in bytes
|
||||
}
|
||||
|
||||
const OrganizationVersion = {
|
||||
|
|
@ -68,8 +65,8 @@ const OrganizationVersion = {
|
|||
description: { type: String },
|
||||
when: [{
|
||||
day: { type: String }, // (Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche)
|
||||
from: ScheduleIntervalBoundary,
|
||||
to: ScheduleIntervalBoundary
|
||||
from: { type: String },
|
||||
to: { type: String }
|
||||
}]
|
||||
}],
|
||||
pricing: [{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue