Wagtail RichTextBlock extend to pick color - wagtail

I am trying to implement a color-chooser option in wagtail RichTextBlock so that I can select any color for my selected text.
This is my wagtail_hooks.py file:
#hooks.register("register_rich_text_features")
def register_colortext_feature(features):
"""Creates centered text in our richtext editor and page."""
# Step 1
feature_name = "Text Color Picker"
type_ = "TEXTCOLOR"
tag = "span"
# Step 2
control = {
"type": type_,
"label": "color",
"description": "Color Text",
# "style": {
# "display": "block",
# "text-align": "center",
# },
}
# Step 3
features.register_editor_plugin(
"draftail", feature_name, draftail_features.InlineStyleFeature(control)
)
# Step 4
db_conversion = {
"from_database_format": {tag: InlineStyleElementHandler(type_)},
"to_database_format": {
"style_map": {
type_: {
"element": tag,
"props": {
"style": "color:colorcode"
}
}
}
}
}
# Step 5
features.register_converter_rule("contentstate", feature_name, db_conversion)
# Step 6, This is optional.
features.default_features.append(feature_name)
Is there anyone who can help me with this? I just tried my best to achieve this but no luck.

Could you add a charfield or charblock to your model or streamblock where you enter the hex value and in the template you read the field value and set the text color to that?

Related

Adding List-/StructBlocks programmatically

i'm new to Wagtail and struggling to create content programmatically from a Django management command.
I have defined a StructBlock and Page with a StreamField like so:
class TaskBlock(blocks.StructBlock):
tasks = blocks.ListBlock(
blocks.StructBlock(
[
("title", blocks.CharBlock()),
("length", blocks.IntegerBlock())
]
)
)
class Meta:
template = "tasks/task_block.html"
icon = "edit"
label = "Task"
class TaskPage(Page):
tasks_first = StreamField([("tasks_first", TaskBlock())], null=True)
content_panels = Page.content_panels + [StreamFieldPanel("tasks_first")]
My command looks like:
class Command(BaseCommand):
def handle(self, *args, **options):
parent_page = Page.objects.get(title="Task Master").specific
task_page = TaskPage(
title="Task Page 5",
slug="task-page-5",
tasks_first=json.dumps(
[
{
"type": "tasks_first",
"value": [
{
"type": "tasks",
"value": [
{"type": "title", "value": "this is a task"},
{"type": "length", "value": 5}
],
}
],
}
]
),
)
parent_page.add_child(instance=task_page)
revision = task_page.save_revision()
revision.publish()
task_page.save()
The page is successfully created with a Task block, but the task is blank and does not contain the test data defined in the json.
I'm probably missing some basic knowledge on how to define the json for the TaskBlock() in the StreamField tasks_first.
Could you give me some guidance?
Probably clearer to start from the inside and work outwards here...
The JSON representation of a StructBlock value is a simple dict, where the keys are the sub-block names and the values are their values - you don't need "type" and "value" here. So, a value for the innermost StructBlock would look like:
{"title": "this is a task", "length": 5}
The value for ListBlock is a list of these values. If we only want one task in the list, this will be:
[
{"title": "this is a task", "length": 5}
]
TaskBlock is a StructBlock with a single sub-block named "tasks", so again this should be a simple dict:
{
"tasks": [
{"title": "this is a task", "length": 5}
]
}
And finally we place this in the stream - this is where the "type" and "value" come in.
[
{
"type": "tasks_first",
"value": {
"tasks": [
{"title": "this is a task", "length": 5}
]
}
}
]
This, then, is what you pass to json.dumps(...).
Finally, are you sure you need a StreamField at all here? If you just want a page with a list of tasks on, you could do this with an InlinePanel where each child object is one task.

Python Selenium ChromeDriver change default margins: to none

Under More settings, chrome (v96) has an option for Margins, which I have selected as none. Here are our options currently for chrome:
Here are our options currently, which are set so that we can save PDFs locally with Selenium:
def make_options(output_dir):
state = {
"recentDestinations": [
{
"id": "Save as PDF",
"origin": "local",
"account": ""
}
],
"selectedDestinationId": "Save as PDF",
"version": 2
}
profile = {'printing.print_preview_sticky_settings.appState': json.dumps(state),
'savefile.default_directory': output_dir,
"download.default_directory": output_dir}
chrome_options = webdriver.ChromeOptions()
chrome_options.headless = False
chrome_options.add_experimental_option('prefs', profile)
chrome_options.add_argument('--kiosk-printing')
return chrome_options
I can see in the PDFs saved with Selenium that Margins is not set to None. Is it possible to update the code above for this? We need Margins: None in the chrome options, setting it in the CSS of the webpage we are saving as PDF does not resolve our issue.
You can set the margin type in the json construct, the option for no Margins is 1. see this link https://github.com/chromium/chromium/blob/eadef3f685cd9e96e94fcb9645b6838b6d0907a8/chrome/browser/resources/print_preview/data/margins.js
edit your code to include this new line:
def make_options(output_dir):
state = {
"recentDestinations": [
{
"id": "Save as PDF",
"origin": "local",
"account": ""
}
],
"selectedDestinationId": "Save as PDF",
"version": 2,
"marginsType": 1
}
profile = {'printing.print_preview_sticky_settings.appState': json.dumps(state),
'savefile.default_directory': output_dir,
"download.default_directory": output_dir}
chrome_options = webdriver.ChromeOptions()
chrome_options.headless = False
chrome_options.add_experimental_option('prefs', profile)
chrome_options.add_argument('--kiosk-printing')
return chrome_options

How to add custom toolbar field inside ckeditor4-react editor?

I am using "ckeditor4-react" editor to add content for an email. I want to add tokens or tags list in it. Is this possible to add custom token select list inside toolbar.
package link:: https://github.com/ckeditor/ckeditor4-react
Please suggest how can I add custom toolbar select list field inside react ckeditor 4.
You can define
const editorToolbar = [
{
name: "basicstyles",
groups: ["basicstyles", "cleanup"],
items: [
"Bold",
"Italic",
"Underline",
"Strike",
"Subscript",
"Superscript",
"-",
"RemoveFormat",
],
},
{
name: "paragraph",
groups: ["list", "indent", "blocks", "align", "bidi"],
items: ["NumberedList", "BulletedList", "-", "Outdent", "Indent"],
},
{ name: "links", items: ["Link", "Unlink"] },
{
name: "insert",
items: ["Image", "SpecialChar"],
},
];
and then use that in config
<CKEditor
name="editor"
config={{toolbar: editorToolbar}}
/>

Display JSON data array from settings_data.json in page template liquid (Shopify)

My setting_data.json (Deput Shopify Theme)file:
{
"current": {
"checkout_error_color": "#ff6d6d",
"sections": {
"header": {
"type": "header",
"settings": {
"align_logo": "left",
"logo": "shopify:\/\/shop_images\/logo_9bb43dd5-21d6-442c-8a19-0f4adf03e13a.png",
"logo_max_width": 100,
"main_linklist": "main-menu",
"message": true,
"home_page_only": true,
"message_text": "Paw Paper – Edible Gift Wrap for Pets",
"message_link": "",
"color_bg": "#162950",
"color_text": "#ffffff"
}
},
How I can get section header variables in Shopify liquid template page?
I can get one variable:
{% assign text_color = settings.color_text %}
{{ text_color }}
I need to show custom block on page and get data for it from settings_data.json
"1543393771012": {
"type": "custom-content",
"blocks": {
"1543393771012-1": {
"type": "image",
"settings": {
"image": "shopify:\/\/shop_images\/info.png",
"width": "50%",
"alignment": "center"
}
},
"1543393802354": {
"type": "html",
"settings": {
"code": "<p>Paw Paper is the world's first edible wrapping paper designed specifically for pets. Our edible paper is 100% all-natural, made from potato starch with Omega-3 enhanced beef flavoring. It's water-soluble so no tape required!<\/p> <p>Just lick it like a stamp or dab water on the edges to bind the seams.<\/p>",
"width": "50%"
}
}
},
But, I can not get and display array with variables.
Help, please.
The settings_data.json file isn't something you can access directly in Liquid - but you can access the values stored within using the appropriate Liquid commands.
The global settings object in Liquid gives you access to all the variables defined in your settings_schema.json file, and nothing more.
However, your color_text setting isn't a theme setting, it's a section setting for the section named 'header'. This variable can be accessed as section.settings.color_text, so long as you are calling that from inside your header section.
Block settings are accessed in a similar way. Assuming that you have some sort of for block in section.blocks loop, those block-level settings can be accessed as block.settings.whatever_key_you_made
Remember - all of the settings you create have a corresponding scope and need to be accessed appropriately! settings_schema.json gives you your global settings object; each section has its private settings object; and each block has it's own personal settings object.
Hope this helps!
Assuming your JSONOBJ is correct.
var JSONOBJ={
"current": {
"checkout_error_color": "#ff6d6d",
"sections": {
"header": {
"type": "header",
"settings": {
"align_logo": "left",
"logo": "shopify:\/\/shop_images\/logo_9bb43dd5-21d6-442c-8a19-0f4adf03e13a.png",
"logo_max_width": 100,
"main_linklist": "main-menu",
"message": true,
"home_page_only": true,
"message_text": "Paw Paper – Edible Gift Wrap for Pets",
"message_link": "",
"color_bg": "#162950",
"color_text": "#ffffff"
}
}}}}
console.log(JSONOBJ.current.sections.header.settings.message_text)

angularjs: extending directive then make modifications

I am working in ServiceNow and am trying to extend an ootb directive, then make some modifications to a couple functions. So far I've figured out how to extend the directive:
function (spModelDirective){
return angular.extend({}, spModelDirective[0], {
templateUrl:'lbl_custom_template.xml'
});
}
Within this directive, there's a function called getNestedFields that I would like to make edits to:
function getNestedFields(fields, containers) {
if (!containers)
return;
for (var _container in containers) {
var container = containers[_container];
if (container.columns) {
for (var _col in container.columns) {
var col = container.columns[_col];
for (var _field in col.fields) {
var field = col.fields[_field];
if (field.type == "container" && container.caption != "")
getNestedFields(fields, [field]);
else if (field.type == "checkbox_container")
getNestedFields(fields, field.containers);
else if (field.type == "field" || container.caption=="")
fields.push(formModel._fields[field.name]);
}
}
}
}
}
Can someone provide some guidance on what the correct syntax for this would be?
More information
Our team cloned the ootb widget-form and am trying to create a custom layout. Basically, we want each form section to be it's own tab much like the back-end form instead of one long form, which is what the ootb widget-form currently does. In the very first line of the sp-variable-layout template, it shows:
<fieldset ng-init="$last ? execItemScripts() : null" ng-show="isContainerVisible(container)" ng-repeat="container in containers">
The ng-repeat of container in containers considers each form section as a separate container (which is perfect), BUT it also considers any splits as a separate container as well. So for example, if my form's layout looks like this:
This will create two tabs: one that has every field within the begin and end splits AND a separate tab with everything after the end split. The JSON object that is created looks like this:
{
"_bootstrap_cells": 6,
"_count": 2,
"visible": true,
"columns": [{
"fields": [{
"name": "type_of_account",
"type": "field"
}, {
"name": "routing_transit_number",
"type": "field"
}]
}, {
"fields": [{
"name": "type_of_payment",
"type": "field"
}, {
"name": "check_digit",
"type": "field"
}]
}],
"caption": "Direct Deposit",
"id": "b456b9d2137ac340177c36328144b0ef",
"scope_name": "x_dnf_table"
}, {
"_bootstrap_cells": 12,
"_count": 1,
"visible": true,
"columns": [{
"fields": [{
"name": "account_number",
"type": "field"
}, {
"name": "account_title",
"type": "field"
}, {
"name": "financial_institution_name",
"type": "field"
}]
}],
"caption": "",
"id": "",
"scope_name": "x_dnf_table"
}
Notice the first "section" has a caption, but ServiceNow treats the split section as its own separate section with no caption at all.
I want to change the spModel directive to produce only containers with captions as their own tab and if a container does NOT have a caption, to append it to the previous container that does have a caption.
I don't think you can edit this function as this is hosted as a file on Servicenow. See https://hi.service-now.com/scripts/app.$sp/directive.spModel.js then just control-f for the getNestedFields.
Per this thread; https://community.servicenow.com/thread/247907#1059129 I believe spModal is just a wrapper for $uibModal.
What you can do is make your own directive on sp_angular_provider.

Resources