I'm working on standard blog project from Sanity Blog and followed This steps to add external links but my external links are still opening in same tab.
I don't know much about sanity. Could you please help me solve it?
blockContent.js
This is how defined annotations
annotations: [
{
name: 'link',
type: 'object',
title: 'External link',
fields: [
{
name: 'href',
type: 'url',
title: 'URL'
},
{
title: 'Open in new tab',
name: 'blank',
description: 'Read https://css-tricks.com/use-target_blank/',
type: 'boolean'
}
]
},
{
name: 'internalLink',
type: 'object',
title: 'Internal link',
fields: [
{
name: 'reference',
type: 'reference',
title: 'Reference',
to: [
{ type: 'post' },
]
}
]
}
]
post-body.js
displaying blog data in this js file
import { PortableText } from "#portabletext/react";
const serializers = {
marks: {
internalLink: ({mark, children}) => {
const {slug = {}} = mark
const href = `/${slug.current}`
return <a href={href}>{children}</a>
}
},
link: ({mark, children}) => {
const { blank, href } = mark
return blank ?
{children}
: <a href={href}>{children}</a>
}
}
...
export default function PostBody({ content }) {
return (
<div className="max-w-2xl mx-auto" className={markdownStyles.markdown}>
<PortableText value={content} components={components}
serializers={serializers} />
</div>
);
}
api.js
Sanity query
export async function getAllPostsWithSlug() {
const data = await client.fetch(`*[_type == "post"]{ 'slug': slug.current }`)
return data
}
Related
I have this code in my chrome extension backround.js file
const bannedHosts = [];
const setupContextMenus = () => {
chrome.contextMenus.create({
id: 'blockHost',
type: 'normal',
contexts: ['all'],
title: 'Block website',
})
chrome.contextMenus.create({
id: 'unblockHost',
type: 'normal',
contexts: ['all'],
title: 'Unblock website',
})
}
chrome.runtime.onInstalled.addListener( () => {
console.log('extension installed')
setupContextMenus()
})
chrome.contextMenus.onClicked.addListener( ( clickData) => {
if( clickData.menuItemId === 'blockHost' ) {
console.log(clickData)
bannedHosts.push(clickData.pageUrl)
chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: bannedHosts.map((h, i) => i + 1),
addRules: bannedHosts.map((h, i) => ({
id: i + 1,
action: {type: 'redirect', redirect: {extensionPath: '/options.html'}},
condition: {urlFilter: `||${h}/`, resourceTypes: ['main_frame', 'sub_frame']},
}))
});
console.log(bannedHosts)
} else if( clickData.menuItemId === 'unblockHost' ) {
...
}
})
I'm doing a quick test of the code by installing the extension, I'm able to see the context menu voices and I'm able to track the click event. My problem is with the declarativeNerRequest, I've noticed that when an url is added to the array blockedHosts, the rule that I want to add that is supposed to redirect the user to the options page will not work and if I try to visit the website it will be displayed instead of redirecting the user.
I have declared the correct permission in manifest v3, how I can fix this problem? How I add correctly a new url and a rule to block it and how I can remove the related url and rule if needed?
manifest file
import { defineManifest } from '#crxjs/vite-plugin'
export default defineManifest({
name: '',
description: '',
version: '1.0.0',
manifest_version: 3,
icons: {
16: 'img/logo-16.png',
32: 'img/logo-34.png',
48: 'img/logo-48.png',
128: 'img/logo-128.png',
},
action: {
// default_popup: 'popup.html',
// default_icon: 'img/logo-48.png',
},
options_page: 'options.html',
background: {
service_worker: 'src/background/index.js',
type: 'module',
},
content_scripts: [
{
matches: ['http://*/*', 'https://*/*'],
js: ['src/content/index.js'],
},
],
host_permissions: [
'<all_urls>'
],
web_accessible_resources: [
{
resources: [
'img/logo-16.png',
'img/logo-34.png',
'img/logo-48.png',
'img/logo-128.png',
'options.html'
],
matches: [
'<all_urls>'
],
},
],
permissions: [
'tabs',
'contextMenus',
'webRequest',
'webRequestBlocking',
'declarativeNetRequest'
]
})
I am writing a gutenberg block which saves the data into meta fields. Problem is that the value is being saved in multiple rows in the database instead of one. How can I save in one row?
For example: 'My apple' is saved as metakeyname: My and metakeyname: apple into the database. I want to save it as metakeyname: My apple
Below is my code. Please help. Thank you!
const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;
const { RichText, PlainText, MediaUpload, InspectorControls } = wp.editor;
const { TextControl, Tooltip, PanelBody, PanelRow, FormToggle, Button } = wp.components;
const el = wp.element.createElement;
registerBlockType('my/fields', {
title: 'My Fields',
description: 'Fill in the required data and press the Update button above',
icon: 'products',
category: 'common',
attributes: {
sku: {type: 'string'},
pdf: {type: 'string'},
gallery: {type: 'string'},
features: {type: 'string'},
brands: {type: 'string'},
category: {type: 'string'},
},
edit: (props) => {
const { attributes, setAttributes } = props;
const [meta, setMeta] = wp.coreData.useEntityProp('postType', 'post', 'meta');
return el(
"div",
null,
el(
"h3",
null,
"Please enter Product name above & details below"
),
el(TextControl, {
label: "SKU:",
value: attributes.sku,
onChange: (newtext) => setAttributes({ sku: newtext }) & setMeta({sku: newtext})
})
);
},
save: function(props) {
return props.attributes.sku;
}
})
I got it finally. I had to define single = true and type while making the particular field available in the rest api.
// Meta in REST API
add_action( 'rest_api_init', 'my_register_meta_fields');
function my_register_meta_fields() {
register_meta( 'post', 'sku', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
));
}
In the project there is an array of objects used for populating the breadcrumb:
export const BREADCRUMBS_LIST = [
{ label: 'Home', path: '/', active: false },
{ label: 'Account', path: '/accounts', active: false },
{ label: 'This Account', path: '/accounts', active: true }
];
it is used to populate the list in the Breadcrumbs component:
import { BREADCRUMBS_LIST } from './...'
...
<Breadcrumbs list={BREADCRUMBS_LIST} />
Everything works fine.
The problem appears when we need to translate those labels based on the user's language. For this, we are using react-intl.
So, I transformed the original array into a component of this form:
import { useIntl } from 'react-intl';
export const BreadcrumbsList = () => {
const intl = useIntl();
return [
{ label: intl.formatMessage({ id: 'Home' }), path: '/', active: false },
{
label: intl.formatMessage({ id: 'Account' }),
path: '/accounts',
active: false
},
{
label: intl.formatMessage({ id: 'This Account' }),
path: '/accounts',
active: true
}
];
};
and use it like this:
<Breadcrumbs list={BreadcrumbsList} />
it seems to be wrong because it returns an error saying:
Cannot read property 'map' of undefined.
In that component, the list was used with map: {list.map(({path, label, active}, index) => {...})
Any ideas how to solve this problem?
Your BreadcrumbsList is actually a custom hook, in order to stick with the Rules of Hooks you need to call it on component's level:
// Add "use" prefix as its a custom hook
const useBreadcrumbsList = () => {
const intl = useIntl();
return [
{ label: intl.formatMessage({ id: "Home" }), path: "/", active: false },
{
label: intl.formatMessage({ id: "Account" }),
path: "/accounts",
active: false,
},
{
label: intl.formatMessage({ id: "This Account" }),
path: "/accounts",
active: true,
},
];
};
// Usage
const Component = () => {
const breadcrumbsList = useBreadcrumbsList();
return <Breadcrumbs list={breadcrumbsList} />;
};
I already parsing API using axios. After that I got the value then I adding to properties Data in Datatable but still not working. The value not parse to Datatable. When I console.log the data is showing. I am use API from https://jsonplaceholder.typicode.com/users.
And hear is my code:
import "./css/jquery.dataTables.css";
import React, { Component } from "react";
import axios from "axios";
const $ = require("jquery");
$.Datatable = require("datatables.net");
export default class Tbl extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
loading: true,
};
}
//option 1
async getUsersData() {
const res = await axios.get("https://jsonplaceholder.typicode.com/users");
console.log(res.data);
this.setState({ loading: false, users: res.data });
}
//option 2
async getUsersData1() {
const res = await axios.get("https://jsonplaceholder.typicode.com/users");
return res.data;
}
componentDidMount() {
//call option 1
this.getUsersData();
this.$el = $(this.el);
this.$el.DataTable({
data: this.state.users, //option 1
data: this.getUsersData1(), //option 2
columns: [
{ title: "Name", data: "name" },
{ title: "Username", data: "username" },
{ title: "Email", data: "email" },
{ title: "Phone", data: "phone" },
{ title: "Website", data: "website" }
],
});
}
componentWillMount() {}
render() {
return (
<table className="display" width="100%"
ref={(el) => (this.el = el)}>
</table>
);
}
}
I already try for option 1 and option 2 but still not working.
Thank,
The problem I can see here is that you initialize the plugin table in incorrect way. In order to include DataTable plugin, you should call as require('datatables.net')(window, $). Then after you have done loading data, you just simply call sync data to table again. Here is the snippet:
const $ = require("jquery");
require("datatables.net")(window, $);
// Keep as you have done
async getUsersData() {
const res = await axios.get("https://jsonplaceholder.typicode.com/users");
console.log(res.data);
this.setState({ loading: false, users: res.data });
}
// Init table data as component is mounted
componentDidMount() {
this.getUsersData().then(() => this.syncTable());
}
// Split as new function to init the datatable
syncTable() {
this.$el = $(this.el);
this.$el.DataTable({
data: this.state.users, //option 1
// data: this.getUsersData1(), //option 2
columns: [
{ title: "Name", data: "name" },
{ title: "Username", data: "username" },
{ title: "Email", data: "email" },
{ title: "Phone", data: "phone" },
{ title: "Website", data: "website" }
]
});
}
Here is the codesandbox for you: https://codesandbox.io/s/gallant-faraday-e25mk?file=/src/App.js
Use the "react-data-table-component" library. It is the best library for the data table.
Run this command to install it
npm install react-data-table-component styled-components
Then you have to import it in the react component page and use it
import DataTable from 'react-data-table-component';
const data = [{ id: 1, title: 'DataTable in ReactJS', year: '2021' } ...];
const columns = [
{
name: 'Name',
selector: 'name',
sortable: true,
},
{
name: 'Username',
selector: 'username',
sortable: true,
},
{
name: 'Email',
selector: 'email',
sortable: true,
},
{
name: 'Phone',
selector: 'phone',
sortable: true,
},
{
name: 'Website',
selector: 'website',
sortable: true,
},
];
class MyComponent extends Component {
render() {
return (
<datatable title="YourBlogCoach" columns="{columns}" data="{data}">
</datatable>
)
}
};
Check here for tutorial
I'm using material-table in a react typescript project. I just copied the example code to my project, but it's not working because of some typings problems.The code is
export interface Entity {
id:string,
name:string,
abc:string,
xyz:string
}
const { totalCount, entities, listLoading } = currentState; //currentState from useSelect
//recreating the Entities to make it mutable as I'm using redux-toolkit which freezes the state and and material-table don't accept freezed state objects
const materialTableEntities=entities?entities.map((entity:Entity) => ({...entity})):[];
// Table columns
const columns = [
{
title: "Name",
field: "name"
},
{
title: "ABC Column",
field: "abc"
},
{
title: "XYZ Column",
field: "xyz"
},
];
return (
<>
<MaterialTable
title=""
columns={columns}
data={materialTableEntities}
actions={[
{
icon: 'save',
tooltip: 'Save Entity',
onClick: (event, rowData) => alert("You saved " + rowData.id) //error on rowData.id
},
{
icon: 'delete',
tooltip: 'Delete Device',
onClick: (event, rowData) => alert("You deleted " + rowData.id) //error on rowData.id
}
]}
options={{
search: true,
actionsColumnIndex: -1
}}
/>
</>
Error is
Property 'id' does not exist on type '{ id: string; name: string; abc:
string; xyz: string; } | { ...; }[]'.
fix by check type before , example :
if( !Array.isArray(rowData)){
console.log(rowData.name)
}