How to create a new content entry via Locomotive CMS RESTful API - ruby-on-rails

I have created a site using LocomotiveCMS, I have created two content types called Photo and Gallery, these content types have a relationship so that I can create image galleries on my site.
I am currently looking to use the RESTful API in order to create multiple content entries for Photo as it traverses through a file.
I can connect to the API with no issue and modify the site etc.
I would assume that the cURL command for a new content entry would take the form of:
curl -X POST -d 'photo[image_id]=blah&photo[gallery]=1234&photo[file]=<filepath>photo[published]=true' 'http://<your site>/locomotive/api/current_site.json?auth_token=xxxx'
However I am unsure how to pass a file through in this command, I have substituted this for for now, how would you write this part?
My fields are set up as follows for Photo:
fields:
- image_id:
label: Image ID
type: string
required: true
localized: false
- file: # Name of the field
label: File
type: file
required: true
localized: false
- gallery: # Name of the field
label: Gallery
type: belongs_to
required: true
localized: false
# Slug of the target content type (eg post if this content type is a comment)
class_name: gallery

I ended up making a Ruby Script to parse files and upload them by sending the post data to
/locomotive/api/content_types/photos/entries.json?auth_token=XXXX

The following code can potentially help with this task:
data = {
content_entry: {
title: 'Title',
image: File.new('media/images/screen.png'),
}
}
HTTMultiParty.post(
"http://localhost:8080/locomotive/content_types/blogs/entries.json?auth_token=#{#token}",
query: data,
headers: { 'Content-Type' => 'application/json' }
)
I'm using HTTMultiParty since we actually need to do a multipart-post. Helpful information on how to do this with curl:
https://github.com/locomotivecms/documentation/pull/175
To get the token you need something like this:
HTTParty.post(
'http://localhost:8080/locomotive/api/tokens.json',
body: { api_key: 'YOUR_API_KEY_HERE' }
)
I hope that helps.

There is an api gem for LocomotiveCMS by now, works for 2.5.x and 3.x https://github.com/locomotivecms/coal
the attribute used need to end with _url for content entry fields with type=file https://github.com/locomotivecms/engine/pull/511/commits/f3a47ba5672b7a560e5edbef93cc9a4421192f0a

Related

Github Pages redirect only works locally, but not on the remote Github server (got 404)

When I click on the tags on the right of my Github pages, it always give me a 404 page. However, when I preview it locally, the redirect seem to work just fine:
I wonder if it has something to do with my _config.yml. I have tried different url and baseurl strings, but still couldn't resolve it.
(Note: This theme was adopted from Chirpy)
Thanks!
Part of my config.yml:
title: Changyu Yan
url: 'https://changyuyan.github.io'
# Only if your site type is GitHub Project sites and doesn't have a custom domain,
# change below value to '/projectname'.
baseurl: ''
timezone: America/Los_Angeles
google_analytics:
id: ''
pv:
# The Google Analytics pageviews switch.
# DO NOT enable it unless you know how to deploy the Google Analytics superProxy.
enabled: false
# the next options only valid when `google_analytics.pv` is enabled.
proxy_url: ''
proxy_endpoint: ''
cache: false # pv data local cache, good for the users from GFW area.
# boolean type, the global switch for ToC in posts.
toc: true
paginate: 10
kramdown:
syntax_highlighter: rouge
syntax_highlighter_opts: # Rouge Options › https://github.com/jneen/rouge#full-options
css_class: highlight
# default_lang: console
span:
line_numbers: false
block:
line_numbers: true
start_line: 1
# DO NOT change this unless you're a Pro user on Jekyll and Web development,
# or you think you're smart enough to change other relevant URLs within this template.
permalink: /posts/:title/
collections:
tabs:
output: true
sort_by: order
defaults:
-
scope:
path: '' # An empty string here means all files in the project
type: posts
values:
layout: post
comments: true # Enable comments in posts.
toc: true # Display TOC column in posts.
breadcrumb:
-
label: Posts
url: /
-
scope:
path: _drafts
values:
comments: false
-
scope:
path: index.html
values:
breadcrumb:
-
label: Posts
-
scope:
path: tags
values:
breadcrumb:
-
label: Home
url: /
-
label: Tags
url: /tabs/tags/
-
scope:
path: categories
values:
breadcrumb:
-
label: Home
url: /
-
label: Categories
url: /tabs/categories/
-
scope:
path: ''
type: tabs # see `site.collections`
values:
layout: page
dynamic_title: true # Hide title in mobile screens.
breadcrumb:
-
label: Home
url: /
sass:
sass_dir: /assets/css
style: compressed
compress_html:
clippings: all
comments: all
endings: all
profile: false
blanklines: false
ignore:
envs: []
exclude:
- vendor
- Gemfile.lock
- Gemfile
- tools
- docs
- README.md
- LICENSE
jekyll-archives:
enabled: [categories, tags]
layouts:
category: category
tag: tag
permalinks:
tag: /tags/:name/
category: /categories/:name/
The archives are working locally and not on GitHub Pages because the jekyll-archives gem is not supported in GitHub Pages. You can see in the notes for Chirpy, under Deploy on GitHub Pages, an option for using GitHub Actions. This should allow you to run unsupported plugins (there is a good tutorial by Aneejian).
Another option is to manually build all your tag pages. You would need to create a tag directory and inside that, create all the tag files (software-engineering.html). Inside those you'd run a for loop for that tag. You have a couple of options:
{% for post in site.tags.software-engineering %}
or
{% for post in site.posts | where: 'tag', 'software-engineering' %}
There are others that may better suit your use-case.
Per the baseurl discussion, you do not need that if you do not use a project directory. If you wanted https://changyuyan.github.io/blog/tags/software-engineering/, you'd need to add baseurl: '/blog ...but it doesn't look like you want that.
Near the top of your _config.yml, set baseurl to the name of the project repo according to the instructions:
# Only if your site type is GitHub Project sites and doesn't have a custom domain,
# change below value to '/projectname'.
baseurl: '/changyuyan.github.io'

AWS QuickSight rails integration authorization code error

I have a rails application that needs to add QuickSight. Found that for these purposes it is necessary to use the get_dashboard_embed_url method. This method returns me the URL, but following it (manually, through an iframe tag) I get this error text
Embedding failed because of invalid URL or authorization code. Both of these must be valid and the authorization code must not be expired for embedding to work.
Where can I find the authenticate code? How can I get it? Thanks for your help
This is how i fetch the url
credential_options = {
client: Aws::STS::Client.new(region: ENV['AWS_REGION']),
role_arn: ENV['QUICK_SIGHT_ROLE_ARN'],
role_session_name: self.user_email
}
assume_role_credential = Aws::AssumeRoleCredentials.new(credential_options)
qs_client = Aws::QuickSight::Client.new({
credentials: assume_role_credential,
region: ENV['AWS_REGION']
})
begin
qs_client.register_user({
identity_type: 'IAM', # accepts IAM, QUICKSIGHT
email: self.user_email,
user_role: 'READER', # accepts ADMIN, AUTHOR, READER, RESTRICTED_AUTHOR, RESTRICTED_READER
iam_arn: ENV['QUICK_SIGHT_ROLE_ARN'],
session_name: self.user,
aws_account_id: ENV['AWS_ACCOUNT_ID'],
namespace: 'default'
})
rescue
end
options = {
aws_account_id: ENV['AWS_ACCOUNT_ID'],
dashboard_id: ENV['QUICK_SIGHT_DASHBOARD_ID'],
identity_type: 'IAM',
session_lifetime_in_minutes: 300,
undo_redo_disabled: false,
reset_disabled: false
}
qs_client.get_dashboard_embed_url(options, {}).embed_url
And how i try to display
iframe src=#url class='w-100 h-100' style='min-height: 500px;'
At the first, sorry for my weak english, but i hope that you'll understand what i mean
Ok, after completing these points, everything began to work for me. Also read "Underwater rocks", this is very important points list which will save you tons of time
Replace my code in question with this
def fetch_url # this method fetch embed dashboard url
credential_options = {
client: Aws::STS::Client.new(
region: ENV['AWS_REGION'],
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
),
role_arn: ENV['QUICK_SIGHT_ROLE_ARN'],
role_session_name: self.user_email # This is attr_accessor :user_email
}
assume_role_credential = Aws::AssumeRoleCredentials.new(credential_options)
qs_client = Aws::QuickSight::Client.new({
credentials: assume_role_credential,
region: ENV['AWS_REGION']
})
begin
qs_client.register_user({
identity_type: 'IAM', # accepts IAM, QUICKSIGHT
email: self.user_email,
user_role: 'READER', # accepts ADMIN, AUTHOR, READER, RESTRICTED_AUTHOR, RESTRICTED_READER
iam_arn: ENV['QUICK_SIGHT_ROLE_ARN'],
session_name: self.user_email,
aws_account_id: 'ENV['AWS_ACCOUNT_ID']',
namespace: 'default'
})
rescue
end
options = {
aws_account_id: ENV['AWS_ACCOUNT_ID'],
dashboard_id: ENV['QUICK_SIGHT_DASHBOARD_ID'],
identity_type: 'IAM',
session_lifetime_in_minutes: 300,
undo_redo_disabled: false,
reset_disabled: false
}
qs_client.get_dashboard_embed_url(options).embed_url
end
Go to Manage QuickSight panel https://your-quicksight-region(us-east-2 for example).quicksight.aws.amazon.com/sn/admin#users and click on "Manage permissions" button (button is placed above of the table with users)
On the new page click on "Create" button and select "Sharing dashboards" checkbox. Set the name of the permission, click on the "Create" button
In your controller action: #url = fetch_url # fetch_url - method from 1 point
Add to your view: iframe src=#url OR you can use a amazon-quicksight-embedding-sdk but for me the iframe works pretty well
Underwater rocks
Remember that dashboard url (which you are get with this method qs_client.get_dashboard_embed_url(options).embed_url) can be used only once, i.e. you can't open two browsers tabs with the same URL. When you are will pass this URL to iframe, this URL will cease to be working and you will no longer be able to use it in others browser windows or others iframe's
Add your app domain to whitelist domains on the QuickSight. You can do it in the Manage QuickSight panel https://your-quicksight-region.quicksight.aws.amazon.com/sn/admin#embedding
!!!IMPORTANT!!! if you are trying to embed dashboard to your localhost:your_server_port_number rails server, then you will always get the error message into the iframe (but if you go to this URL through the address bar of the browser, then you should see your dashboard (comment out / remove the iframe so it doesn't use the link, because every embedded dashboard url is disposable)). This is because localhost:your_server_port_number is not provided in the whitelist (Underwater rocks p.2). For resolving this issue and testing your work you can use ngrok (maybe it's available only for macOS, i'm not sure).
When you'll download the ngrok open your terminal and run command
$ ./path_to_ngrok_script/./ngrok http your_server_port_number
For me it's:
$ ~/./scripts/ngrok http 3000
After that do these 3 things for adding your work station to QuickSight whitelist:
In the terminal with ngrok copy generated domain which starts with
the https (i'll name it ngrok_domain), NOT WITH HTTP. For
example: https://047956358355.ngrok.io
Go to the Underwater rocks p.2 and add ngrok_domain
Open your browser and go to the path with iframe, but use ngrok_domain instead of localhost:3000. For example, your embedded dashboard path is localhost:3000/embed_dashboard. Change it to https://047956358355.ngrok.io/embed_dashboard
After all these steps all is start working for me. I'm sure that some of the points here are superfluous, but i'm really tired of working with this integration, so here you yourself decide what should be left and what should be removed.
I hope my answer helped at least someone

React Native - Interact with API - Special Characters Causing Issues - What's the best way to do this?

I cannot consistently successfully send form variables that may/may not include special characters e.g. ? & #
Depending on where I try to escape the chars I encounter different errors when reading the data server-side.
I am aware that an update is due for React Native 0.7 to include formdata but wondered if I could safely post objects without needing this.
Someone has already posted a similar issue but no example code was posted to illustrate the POST working:
How to post a form using fetch in react native?
I have tried - amongst other things :
fetch(APIURL, {
method: 'POST',
body: JSON.stringify({
object1: {
param1a: "value 1a",
param1b: "value 1b - with bad chars & # ?",
},
object2:
{
param2a: "value 2a",
param2b: 0,
}
})
})
but it groups the data into a single unnamed parameter (changing the API to accept this is not an option).
also this:
fetch(APIURL, {
method: 'GET',
accessPackage: JSON.stringify({
accessToken: "abc123",
tokenType: 2,
}),
taggData: JSON.stringify({
title: "test",
wishlistID: 0,
anotherVar: "anotherVal"
})
})
I wish to receive the data as two strings that can be parsed as json objects at the other end.
Looking at the the fetch repo https://github.com/github/fetch hasn't helped as this assumes the post with be a full JSON post (which it isn't) or uses FormData which isn't available to React Native yet.
Another solution may be to safely encode/serialise all of the data to URL parameters but this has also proven inconsistent so far especially with the # char.
What's the best way to do this?
"it groups the data into a single unnamed parameter (changing the API
to accept this is not an option)."
It would, because you've set the post body. This is how it's supposed to work.
I wish to receive the data as two strings that can be parsed as json objects at the other end.
You can do whatever you want, but there's no magic happening here. You will receive a single string, the string you set body to. Likewise, the post body can contain anything but shouldn't get confused with "special" characters. Most likely it is your server-side that is causing the problems.
If you want to use FormData then I think it'll be in v0.7.0 which should be out any day now, or you could probably just include the JS file in your own project. You can find it here. Usage examples are in the UIExplorer demo.

Using w2ui with Rails: Submitting a form

I am trying to build a Rails application with w2ui.
I have hit my first snag when trying to submit a form built with w2ui.
I have a simple model called Project with two attributes: name and description.
The standard, scaffolded form built by Rails submits the form data as follows:
project[name]:Test Project
project[description]:A description
However, the form data submitted by w2ui looks as follows:
record[project[name]]:Test Project
record[project[description]]:A description
That is, w2ui wraps the data further in a record variable, which means I must either change the controller in Rails, which I am not wanting to do, or find a way to get w2ui to not wrap the data the way it does.
My code for w2ui is taken pretty much straight from their demos:
$(function () {
$('#project_form').w2form({
name : 'project_form',
url : '/projects.json',
fields: [
{ name: 'project[name]', type: 'text', required: true },
{ name: 'project[description]', type: 'text' }
],
actions: {
reset: function () {
this.clear();
},
save: function () {
this.submit(); // tried .save() as well, same result
}
}
});
});
First prize would be if w2ui could be configured to do this. Any ideas? I don't see anything in the w2ui docs...
I faced the same problem and straight away could not get a solution.
I added the below to form options, it just copies all params inside record to post data.
onSubmit: function(formName, formObj){
$.extend(formObj.postData, formObj.postData.record);
},
Its been long you have asked this question, if you knew a better solution please let me know.

Using the Symfony admin generator to let a user manage a subset of record

My first post here, hopefully It will be right! =)
I am creating a site to manage web application development using symfony 1.4 and doctrine.
My records consist for this problem of Project and ProjectFeatures
Now what I want to do is use the admin generator to let users manage the features for one project thru a link constraining all the returned features by project_id, that would look like: http://mysite/member/project/:project_id/features
in my routing.yml configuration, I have:
member_project_feature:
class: sfDoctrineRouteCollection
options:
model: ProjectFeature
module: memberProjectFeature
prefix_path: /member/project/:project_id/features
with_show: true
column: id
with_wildcard_routes: true
project_id is an existing column in the model ProjectFeature,
I will use a custom query to retrieve features only by that project_id.
Now I can generate a url to link to that admin generator module without error using:
url_for('member_project_feature', array('project_id' => $project['id']))
And the routing system does recognise the url:
May 04 14:30:59 symfony [info] {sfPatternRouting} Match route "member_project_feature" (/member/project/:project_id/features.:sf_format) for /member/project/1/features with parameters array ( 'module' => 'memberProjectFeature', 'action' => 'index', 'sf_format' => 'html', 'project_id' => '1',)
But the admin generator can't generate it's links inside it's templates with that prefix_path and returns error InvalidArgumentException with message The "/member/project/:project_id/features/:action/action.:sf_format" route has some missing mandatory parameters (:project_id).
Any idea?
Well I found my answer at this url: http://www.blogs.uni-osnabrueck.de/rotapken/?s=symfony
But I will give it here and shorten it because, stackoverflow is awesome and it should be there for a long time =)
1st - The routing configuration I used in my question is valid.
2nd - You need to add a method in the action file generated by the admin
public function execute($sfRequest)
{
// taken from http://www.blogs.uni-osnabrueck.de/rotapken/?s=symfony
$this->forward404Unless(
$project_id = $sfRequest->getUrlParameter('project_id'));
$this->forward404Unless(
$this->project = Doctrine::getTable('ttcWebProject')->find($project_id));
$this->getContext()->getRouting()
->setDefaultParameter('project_id', $project_id);
if ($id = $sfRequest->getUrlParameter('id'))
{
$this->getContext()->getRouting()->setDefaultParameter('id', $id);
}
$result = parent::execute($sfRequest);
return $result;
}
At this point the url gets generated correctly but here is the last step to get to the end result you most probably want to achieve:
3rd - To get the list by project_id I can either provide a table method in the generator.yml, a default value to the getFilterDefaults or this method in the action file:
protected function buildQuery ()
{
$q = parent::buildQuery();
$rootAlias = $q->getRootAlias();
$q->andWhere("{$rootAlias}.project_id = ?",
$this->getRequest()->getUrlParameter('project_id'));
return $q;
}
I'm not 100% certain about what you're trying to do here, but it sounds like you need the ProjectFeature::toParams method return the project_id.

Resources