@elementor/editor-site-navigation 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.7.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.6.2...@elementor/editor-site-navigation@0.7.0) (2023-06-25)
7
+
8
+
9
+ ### Features
10
+
11
+ * **api:** add PostsData class for managing post data and API interactions [ED-11021] ([#57](https://github.com/elementor/elementor-packages/issues/57)) ([a7b93ac](https://github.com/elementor/elementor-packages/commit/a7b93acfc00076f9452cf86f04670412c42b5773))
12
+
13
+
14
+
15
+
16
+
17
+ ## [0.6.2](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.6.1...@elementor/editor-site-navigation@0.6.2) (2023-06-13)
18
+
19
+ **Note:** Version bump only for package @elementor/editor-site-navigation
20
+
21
+
22
+
23
+
24
+
6
25
  ## [0.6.1](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.6.0...@elementor/editor-site-navigation@0.6.1) (2023-06-11)
7
26
 
8
27
  **Note:** Version bump only for package @elementor/editor-site-navigation
package/README.md CHANGED
@@ -3,3 +3,51 @@
3
3
  > **Warning**
4
4
  >
5
5
  > This package is under development and not ready for production use.
6
+
7
+ ## Code examples
8
+
9
+ **Get all pages and create a new one:**
10
+
11
+ ```
12
+ import * as React from 'react';
13
+ import { useEffect } from 'react';
14
+ import { usePosts } from './use-posts';
15
+
16
+ const PageList = () => {
17
+ const { getPosts: getPages, createPost: createPage, isLoading, posts } = usePosts( 'page' );
18
+
19
+ useEffect( () => {
20
+ getPages();
21
+ }, [ getPages ] );
22
+
23
+ const createNewPage = () => {
24
+ const newPage = {
25
+ title: 'New Page',
26
+ content: 'This is a demo page',
27
+ status: 'publish',
28
+ };
29
+
30
+ createPage( newPage );
31
+ };
32
+
33
+ if ( isLoading ) {
34
+ return <div>Loading...</div>;
35
+ }
36
+
37
+ return (
38
+ <div>
39
+ <h1>Pages</h1>
40
+ <button onClick={ createNewPage }>Create New Page</button>
41
+ <ul>
42
+ {
43
+ posts.map( ( page ) => (
44
+ <li key={ page.id }>{ page.title }</li>
45
+ ) )
46
+ }
47
+ </ul>
48
+ </div>
49
+ );
50
+ };
51
+
52
+ export default PageList;
53
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-site-navigation",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -29,11 +29,11 @@
29
29
  },
30
30
  "scripts": {
31
31
  "build": "tsup src/index.ts --format esm,cjs --dts --clean",
32
- "dev": "tsup src/index.ts --format esm --clean"
32
+ "dev": "tsup --config=../../tsup.dev.ts"
33
33
  },
34
34
  "dependencies": {
35
- "@elementor/editor-app-bar": "^0.6.1",
36
- "@elementor/editor-documents": "^0.8.1",
35
+ "@elementor/editor-app-bar": "^0.6.2",
36
+ "@elementor/editor-documents": "^0.8.2",
37
37
  "@elementor/icons": "^0.4.0",
38
38
  "@elementor/ui": "^1.4.50",
39
39
  "@wordpress/api-fetch": "^6.27.0",
@@ -46,5 +46,5 @@
46
46
  "elementor": {
47
47
  "type": "extension"
48
48
  },
49
- "gitHead": "70a2c6139730b7afa69d13eb65023b0e6612f23b"
49
+ "gitHead": "ad9032e095915dbef0f8543d83f73b9288adc8ad"
50
50
  }
@@ -0,0 +1,13 @@
1
+ export interface Post {
2
+ id: number;
3
+ title: string;
4
+ content: string;
5
+ }
6
+
7
+ export interface PostType {
8
+ name: string;
9
+ slug: string;
10
+ labels: Record<string, string>;
11
+ rest_base: string;
12
+ rest_namespace: string;
13
+ }
@@ -0,0 +1,64 @@
1
+ import { useState, useEffect, useMemo } from 'react';
2
+ import { PostType } from './types/interfaces';
3
+ import apiFetch from '@wordpress/api-fetch';
4
+
5
+ type PostTypesResponse = Record<string, PostType>;
6
+
7
+ // allowedPostTypes is only used to filter irrelevant types when fetching all post types.
8
+ // You can still use a specific post type name to fetch a post type not present in allowedPostTypes.
9
+ const allowedPostTypes = [ 'page' ];
10
+
11
+ const useFetchPostTypes = (
12
+ postTypeName?: string
13
+ ): ( PostType | null )[] => {
14
+ const [ postTypes, setPostTypes ] = useState<( PostType | null )[]>( [] );
15
+
16
+ useEffect( () => {
17
+ const fetchPostTypes = async () => {
18
+ try {
19
+ const response: PostTypesResponse = await apiFetch( {
20
+ path: '/wp/v2/types',
21
+ } );
22
+
23
+ if ( postTypeName ) {
24
+ const specificPostType = response[ postTypeName ];
25
+
26
+ setPostTypes( [
27
+ specificPostType
28
+ ? { ...specificPostType }
29
+ : null,
30
+ ] );
31
+ } else {
32
+ const filteredResponse: PostTypesResponse = {};
33
+
34
+ allowedPostTypes.forEach( ( type ) => {
35
+ if ( response[ type ] ) {
36
+ filteredResponse[ type ] = response[ type ];
37
+ }
38
+ } );
39
+
40
+ const filteredPostTypes: ( PostType | null )[] = Object.keys( filteredResponse ).map(
41
+ ( key ) => ( { ...filteredResponse[ key ] } )
42
+ );
43
+
44
+ setPostTypes( filteredPostTypes );
45
+ }
46
+ } catch ( error ) {
47
+ // eslint-disable-next-line no-console
48
+ console.error( 'Error fetching post types:', error );
49
+ }
50
+ };
51
+
52
+ fetchPostTypes();
53
+ }, [ postTypeName ] );
54
+
55
+ return postTypes;
56
+ };
57
+
58
+ export const usePostTypes = (
59
+ postTypeName?: string
60
+ ): ( PostType | null )[] => {
61
+ const postTypes = useFetchPostTypes( postTypeName );
62
+
63
+ return useMemo( () => postTypes, [ postTypes ] );
64
+ };
@@ -0,0 +1,123 @@
1
+ import { useEffect, useMemo, useState, useCallback } from 'react';
2
+ import { usePostTypes } from './use-post-types';
3
+ import { Post, PostType } from './types/interfaces';
4
+ import apiFetch from '@wordpress/api-fetch';
5
+
6
+ const defaultRestNamespace = 'wp/v2';
7
+
8
+ const useFetchPosts = ( postType: PostType | null | undefined ): [ Post[], () => void, boolean ] => {
9
+ const [ posts, setPosts ] = useState<Post[]>( [] );
10
+ const [ isLoading, setIsLoading ] = useState( false );
11
+
12
+ const fetchPosts = useCallback( () => {
13
+ setIsLoading( true );
14
+
15
+ const path = postType
16
+ ? `/${ postType.rest_namespace }/${ postType.rest_base }`
17
+ : `/${ defaultRestNamespace }/posts`;
18
+
19
+ apiFetch( { path } )
20
+ .then( ( response ) => {
21
+ if ( Array.isArray( response ) ) {
22
+ setPosts( response );
23
+ }
24
+ } )
25
+ .catch( ( error ) => {
26
+ // eslint-disable-next-line no-console
27
+ console.error( 'Error fetching posts:', error );
28
+ } )
29
+ .finally( () => {
30
+ setIsLoading( false );
31
+ } );
32
+ }, [ postType ] );
33
+
34
+ useEffect( () => {
35
+ fetchPosts();
36
+ }, [ fetchPosts ] );
37
+
38
+ return [ posts, fetchPosts, isLoading ];
39
+ };
40
+
41
+ const useUpdatePost = ( postType: PostType | null | undefined ): ( ( postId: number, updatedPost: Partial<Post> ) => void ) => {
42
+ return ( postId: number, updatedPost: Partial<Post> ) => {
43
+ const path = postType
44
+ ? `/${ postType.rest_namespace }/${ postType.rest_base }`
45
+ : `/${ defaultRestNamespace }/posts`;
46
+
47
+ apiFetch( {
48
+ path: `/${ path }/${ postId }`,
49
+ method: 'POST',
50
+ data: updatedPost,
51
+ } )
52
+ .catch( ( error ) => {
53
+ // eslint-disable-next-line no-console
54
+ console.error( 'Error updating post:', error );
55
+ } );
56
+ };
57
+ };
58
+
59
+ const useCreatePost = ( postType: PostType | null | undefined ): ( ( newPost: Partial<Post> ) => void ) => {
60
+ return ( newPost: Partial<Post> ) => {
61
+ const path = postType
62
+ ? `/${ postType.rest_namespace }/${ postType.rest_base }`
63
+ : `/${ defaultRestNamespace }/posts`;
64
+
65
+ apiFetch( {
66
+ path,
67
+ method: 'POST',
68
+ data: newPost,
69
+ } )
70
+ .catch( ( error ) => {
71
+ // eslint-disable-next-line no-console
72
+ console.error( 'Error creating post:', error );
73
+ } );
74
+ };
75
+ };
76
+
77
+ const useDeletePost = ( postType: PostType | null | undefined ): ( ( postId: number ) => void ) => {
78
+ return ( postId: number ) => {
79
+ const path = postType
80
+ ? `/${ postType.rest_namespace }/${ postType.rest_base }`
81
+ : `/${ defaultRestNamespace }/posts`;
82
+
83
+ apiFetch( {
84
+ path: `/${ path }/${ postId }`,
85
+ method: 'DELETE',
86
+ } )
87
+ .catch( ( error ) => {
88
+ // eslint-disable-next-line no-console
89
+ console.error( 'Error deleting post:', error );
90
+ } );
91
+ };
92
+ };
93
+
94
+ export const usePosts = ( postType?: string | null ): {
95
+ posts: Post[];
96
+ getPosts: () => void;
97
+ updatePost: ( postId: number, updatedPost: Partial<Post> ) => void;
98
+ createPost: ( newPost: Partial<Post> ) => void;
99
+ deletePost: ( postId: number ) => void;
100
+ isLoading: boolean;
101
+ } => {
102
+ const postTypes = usePostTypes();
103
+ const postTypeData = postTypes.find( ( type ) => type?.name === postType );
104
+
105
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
106
+ const [ posts, fetchPosts, isLoading ] = useFetchPosts( postTypeData );
107
+ const updatePost = useUpdatePost( postTypeData );
108
+ const createPost = useCreatePost( postTypeData );
109
+ const deletePost = useDeletePost( postTypeData );
110
+
111
+ const getPosts = useMemo( () => {
112
+ return () => posts;
113
+ }, [ posts ] );
114
+
115
+ return {
116
+ posts,
117
+ getPosts,
118
+ updatePost,
119
+ createPost,
120
+ deletePost,
121
+ isLoading,
122
+ };
123
+ };