matcornic / hermes

Golang package that generates clean, responsive HTML e-mails for sending transactional mail
Apache License 2.0
2.83k stars 246 forks source link

Plugin system? #5

Open FGRibreau opened 7 years ago

FGRibreau commented 7 years ago

Hello !

Is a plugin system planned on Hermes roadmap? :)

I would live to develop one to add support for image charts to hermes. (like I did for mjml with mjml-charts)

matcornic commented 7 years ago

Hi @FGRibreau !

No plugin system planned yet :).

Mjml is a framework, Hermes is not. Basically, Hermes is just Golang HTML templates describing typical emails ^^ (containing optional button, table, and so on). It's not meant to be as flexible as Mjml. User defines data and theme displays data as it wants.

Without any plugin system, a simple idea could be to add a Chart in Email.Body. But, every built-in theme will have to implement charts.

Can you give us more details of your idea and how it would be used with Hermes ? Do you want to include charts with your https://image-charts.com service ?

FGRibreau commented 7 years ago

Without any plugin system, a simple idea could be to add a Chart in Email.Body. But, every built-in theme will have to implement charts.

Yes, that would be nice, who does not want to add charts to reports ? :)

Can you give us more details of your idea and how it would be used with Hermes ?

I could think of somthing like this:

type Chart struct {
    params map[string]string
}

Note that we could generate automatically generate the struct from the swagger/openapi specification like we did for mjml-chart thus offering automatic documentation and tests :) But it would be better as an plugin (so we could automatically update it) since here it's not planned it might not be the best idea ^^

Do you want to include charts with your https://image-charts.com service ?

That's why we created image-charts in the first place indeed, it was to hard for each project to setup server-side chart rendering, storage and scaling.

matcornic commented 7 years ago

I think chart addition would be great !

Although, I think Chart struct should be more service-agnostic as possible, meaning it should contains points or something, not just params (it may not be possible depending on the kind of chart ?).

Maybe using an interface instead of struct would be nice, meaning we could have a plugin-like system.

Next step would be to propose a Chart type here, then community could debate on it 👍

FGRibreau commented 7 years ago

Hi @matcornic !

Although, I think Chart struct should be more service-agnostic as possible, meaning it should contains points or something, not just params (it may not be possible depending on the kind of chart ?).

As you can see, it highly depends on the backend, Image-Charts follows Google Image Charts API so we could be our attributes on that but that does a LOT of attributes (the good news is we could definitely generate the Chart struct from the swagger.json spec and only keep the completely compatible parameters between the two (just like we did in mjml-chart) and offer a way to change the endpoint so the deprecated Google Image Charts and Image-Charts will be supported.

What do you think?

matcornic commented 7 years ago

@FGRibreau I think this is the way to go 😉

Seeing the (big) swagger spec, I think that some fields don't need to be in the final struct. Just keep it as simple as possible, with convention over configuration principle in mind. I don't want the users to be overwhelmed with an overcomplicated Chart struct.

Thank you again for your proposal. I assign you to the issue 😛

FGRibreau commented 7 years ago

Here is a first try:

type Chart struct {
  // (optional) Image-Charts or Google Image Charts endpoint
  endpoint string
  // (required) chart type
  cht string
  // (required) chart data
  chd string
  // (optional) text format custom scaling
  chds string
  // (optional) output fake format
  chof string
  // (required) chart size
  chs string
  // (optional) text for each series, to display in the legend
  chdl string
  // (optional) chart legend text and style
  chdls string
  // (optional) grid lines
  chg string
  // (optional) series colors
  chco string
  // (optional) chart title
  chtt string
  // (optional) chart title colors and font size
  chts string
  // (optional) line thickness and solid/dashed style
  chls string
  // (optional) pie chart labels
  chl string
  // (optional) Background Fills
  chf string
  // (optional) gif configuration
  chan string
  // (optional) doughnut chart inside label
  chli string
  // (optional) image-charts enterprise `account_id`
  icac string
  // (optional) HMAC-SHA256 signature
  ichm string
  // (optional) Force watermark display even if the chart was signed with an enterprise account
  icwt bool
}

I used this simple JS code to generate it:

console.log(`
type Chart struct {
  // (optional) Image-Charts or Google Image Charts endpoint
  endpoint string
${swagger.paths['/chart'].get.parameters
  .filter(x => x['x-meta'].implementation.status === 'COMPLETE')
  .map(x => `  // (${x.required ? 'required' : 'optional'}) ${x.description}\n  ${x.name} ${x.type === 'boolean' ? 'bool' : x.type}`)
  .join('\n')}
}`);

I'm not a go expert, so I did not generate the constructor but it will only asks for the required values (cht, chd and chs) and it will validate through regexp (extracted from swagger schema) the specified value

matcornic commented 7 years ago

Ok Nice ! You may have to set struct properties as public for them to be available in the Go templating. (Just uppercase the first letter) I'm not sure private functions and properties are available Or maybe easier, create a public function on Chart type, rendering the needed URL, and just use this function in the template.

Note: I'm on holidays for a week, so I probably won't be able to help you until then 🌎🌍🌏

FGRibreau commented 7 years ago

Hello @matcornic,

Oh did not see that you were from Rennes! (I'm from Nantes) are you going to Breizh Camp? I will!

matcornic commented 7 years ago

@FGRibreau So will I ;)

FGRibreau commented 7 years ago

Awesome, see you there! I will give 2 talks there "Construire et automatiser l'ecosystème de son SaaS grâce à une spécification Swagger" & "Une API REST et GraphQL sans code grâce à Postgrest, Sub0 et PostgreSQL", hope to see you there !