Maison > interface Web > js tutoriel > Création d'un planificateur personnalisé à l'aide de React et Supabase

Création d'un planificateur personnalisé à l'aide de React et Supabase

Susan Sarandon
Libérer: 2024-12-18 07:08:15
original
301 Les gens l'ont consulté

Introduction

La planification est l'une des fonctionnalités essentielles des applications modernes. Cela peut nous permettre d'exécuter des tâches périodiques pouvant être automatisées. Tâches telles que l'envoi de rappels, la planification de publications, la mise à jour des données ou l'automatisation des flux de travail.

Donc, dans cet article, nous allons construire un planificateur pour publier des articles sur dev.to. Bien que dev.to ait des fonctionnalités de planification, nous allons les implémenter à notre manière, qui peuvent être utilisées pour créer tout type d'application de planification.

Alors, commençons.

Pile technologique

Nous allons utiliser la pile technologique suivante :

  • React : Nous allons utiliser React, particulièrement ViteJS avec React pour construire le fronted.
  • Supabase : Il fournit une solution tout-en-un pour créer des applications. Il fournit une base de données, une authentification, un stockage, une fonction Edge et bien d'autres. Nous allons utiliser ce qui suit de Supbase :
    • Base de données : ceci est utilisé pour stocker les informations sur l'article et planifier l'heure.
    • Cron Job : pour exécuter périodiquement pour appeler la fonction Edge
    • Fonction Edge : cela vérifiera si un article a l'heure actuelle comme heure programmée. Si c'est le cas, il publiera l'article.

Cela suffira pour créer facilement une application de planification.

Travailler sur l'application

Discutons du fonctionnement de l'application, ce qui permet de comprendre assez facilement le flux de l'application. Voici les flux un par un :

  1. Ajout d'articles à la base de données via le front-end.
  2. La tâche Cron s'exécutera toutes les minutes pour appeler la fonction Edge.
  3. Une fonction Edge sera exécutée pour vérifier l'heure actuelle comme l'article programmé. S'il y a un article, il publiera l'article.
  4. Les données des articles dans le tableau des publications seront mises à jour. # Construire le frontend

L'interface du bâtiment est devenue calme ces derniers temps avec beaucoup d'IA générative. L’une des IA que nous allons utiliser est bolt.new. Pourquoi bolt.new ? Il peut générer des applications React complètes avec des dépendances et toutes les configurations telles que tailwindcss. Vous pouvez directement éditer des articles à l'aide de StackBlitz et également déployer l'application. Si vous en avez besoin, vous pouvez télécharger le code pour l'exécuter localement. Le point bonus est qu'il s'intègre assez bien à Supabase afin que vous puissiez générer une application React fonctionnelle avec l'intégration Supbase.

Je l'ai utilisé pour générer le front. Voici toutes les pages.

App.tsx

Cela gérera la page d'affichage des composants et fournira la page de destination.

    function App() {
      const [posts, setPosts] = useState<ScheduledPost[]>([]);
      const handleSchedulePost = async (data: CreatePostData) => {
        // In a real app, this would make an API call to your edge function
        const newPost: ScheduledPost = {
          content: data.content,
          scheduled_time: data.scheduledTime,
          status: 'pending',
          title: data.title,
          tags: data.tags
        };
        const { error } = await supabase
      .from('scheduled_posts')
      .insert(newPost)
      if (error){
        alert(`Erorr: ${error}`)
        return
      }
        // setPosts((prev) => [...prev, newPost]);
      };
      const fetchScheduedPost = async () => {
        const { data, error } = await supabase
      .from('scheduled_posts')
      .select()
      if(error){
        alert(`Erorr Fetching Data: ${error}`)
        return
      }
      setPosts(data)
      } 
      useEffect(() => {
        fetchScheduedPost()
      },[])
      return (
        <div className="min-h-screen bg-gray-50">
          <header className="bg-white shadow-sm">
            <div className="max-w-4xl mx-auto px-4 py-4">
              <div className="flex items-center gap-2">
                <Newspaper className="h-8 w-8 text-blue-500" />
                <h1 className="text-xl font-bold text-gray-900">Dev.to Post Scheduler</h1>
              </div>
            </div>
          </header>
          <main className="max-w-4xl mx-auto px-4 py-8">
            <div className="grid gap-8 md:grid-cols-2">
              <div>
                <h2 className="text-xl font-semibold text-gray-800 mb-4">Schedule New Post</h2>
                <PostForm onSubmit={handleSchedulePost} />
              </div>
              <div>
                <ScheduledPosts posts={posts} />
              </div>
            </div>
          </main>
        </div>
      );
    }
    export default App;
Copier après la connexion
Copier après la connexion

SchudledPost.tsx

Cela affiche les articles programmés.

    const StatusIcon = ({ status }: { status: ScheduledPost['status'] }) => {
      switch (status) {
        case 'posted':
          return <CheckCircle className="h-5 w-5 text-green-500" />;
        case 'failed':
          return <XCircle className="h-5 w-5 text-red-500" />;
        default:
          return <Clock3 className="h-5 w-5 text-yellow-500" />;
      }
    };
    export function ScheduledPosts({ posts }: ScheduledPostsProps) {
      return (
        <div className="space-y-4">
          <h2 className="text-xl font-semibold text-gray-800">Scheduled Posts</h2>
          {posts.length === 0 ? (
            <p className="text-gray-500 text-center py-8">No scheduled posts yet</p>
          ) : (
            <div className="space-y-4">
              {posts.map((post, index) => (
                <div
                  key={index}
                  className="bg-white p-4 rounded-lg shadow-md border border-gray-100"
                >
                  <div className="flex items-start justify-between">
                    <div className="flex-1">
                      <p className="text-gray-800 mb-2">{post.title}</p>
                      <div className="flex items-center gap-4 text-sm text-gray-500">
                        <div className="flex items-center gap-1">
                          <Calendar className="h-4 w-4" />
                          {new Date(post.scheduled_time).toLocaleDateString()}
                        </div>
                        <div className="flex items-center gap-1">
                          <Clock className="h-4 w-4" />
                          {new Date(post.scheduled_time).toLocaleTimeString()}
                        </div>
                      </div>
                    </div>
                    <StatusIcon status={post.status} />
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      );
    }
Copier après la connexion
Copier après la connexion

PostForm.tsx

Cela gérera le formulaire où l'utilisateur pourra donner des informations sur l'article.

    function App() {
      const [posts, setPosts] = useState<ScheduledPost[]>([]);
      const handleSchedulePost = async (data: CreatePostData) => {
        // In a real app, this would make an API call to your edge function
        const newPost: ScheduledPost = {
          content: data.content,
          scheduled_time: data.scheduledTime,
          status: 'pending',
          title: data.title,
          tags: data.tags
        };
        const { error } = await supabase
      .from('scheduled_posts')
      .insert(newPost)
      if (error){
        alert(`Erorr: ${error}`)
        return
      }
        // setPosts((prev) => [...prev, newPost]);
      };
      const fetchScheduedPost = async () => {
        const { data, error } = await supabase
      .from('scheduled_posts')
      .select()
      if(error){
        alert(`Erorr Fetching Data: ${error}`)
        return
      }
      setPosts(data)
      } 
      useEffect(() => {
        fetchScheduedPost()
      },[])
      return (
        <div className="min-h-screen bg-gray-50">
          <header className="bg-white shadow-sm">
            <div className="max-w-4xl mx-auto px-4 py-4">
              <div className="flex items-center gap-2">
                <Newspaper className="h-8 w-8 text-blue-500" />
                <h1 className="text-xl font-bold text-gray-900">Dev.to Post Scheduler</h1>
              </div>
            </div>
          </header>
          <main className="max-w-4xl mx-auto px-4 py-8">
            <div className="grid gap-8 md:grid-cols-2">
              <div>
                <h2 className="text-xl font-semibold text-gray-800 mb-4">Schedule New Post</h2>
                <PostForm onSubmit={handleSchedulePost} />
              </div>
              <div>
                <ScheduledPosts posts={posts} />
              </div>
            </div>
          </main>
        </div>
      );
    }
    export default App;
Copier après la connexion
Copier après la connexion

Fonction de bord

Les fonctions Edge sont des fonctions TypeScript côté serveur, distribuées globalement en périphérie, à proximité de vos utilisateurs. Ils peuvent être utilisés pour écouter des webhooks ou intégrer votre projet Supabase avec des tiers comme Stripe. Les fonctions Edge sont développées à l'aide de Deno.

Pour exécuter et déployer la fonction Edge localement, vous devez disposer des éléments suivants :

  • Supbase CLI : Vous pouvez installer la CLI localement à l'aide de ce guide. C'est simple en utilisant simplement le npm et le npx.
  • Docker Desktop : installez le bureau Docker à partir d'ici.

Ainsi, après avoir installé ceci, vous pouvez utiliser votre répertoire de code frontend ou autre pour créer la fonction Supabase Edge.

Exécutez la commande ci-dessous pour lancer un projet supabase :

    const StatusIcon = ({ status }: { status: ScheduledPost['status'] }) => {
      switch (status) {
        case 'posted':
          return <CheckCircle className="h-5 w-5 text-green-500" />;
        case 'failed':
          return <XCircle className="h-5 w-5 text-red-500" />;
        default:
          return <Clock3 className="h-5 w-5 text-yellow-500" />;
      }
    };
    export function ScheduledPosts({ posts }: ScheduledPostsProps) {
      return (
        <div className="space-y-4">
          <h2 className="text-xl font-semibold text-gray-800">Scheduled Posts</h2>
          {posts.length === 0 ? (
            <p className="text-gray-500 text-center py-8">No scheduled posts yet</p>
          ) : (
            <div className="space-y-4">
              {posts.map((post, index) => (
                <div
                  key={index}
                  className="bg-white p-4 rounded-lg shadow-md border border-gray-100"
                >
                  <div className="flex items-start justify-between">
                    <div className="flex-1">
                      <p className="text-gray-800 mb-2">{post.title}</p>
                      <div className="flex items-center gap-4 text-sm text-gray-500">
                        <div className="flex items-center gap-1">
                          <Calendar className="h-4 w-4" />
                          {new Date(post.scheduled_time).toLocaleDateString()}
                        </div>
                        <div className="flex items-center gap-1">
                          <Clock className="h-4 w-4" />
                          {new Date(post.scheduled_time).toLocaleTimeString()}
                        </div>
                      </div>
                    </div>
                    <StatusIcon status={post.status} />
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      );
    }
Copier après la connexion
Copier après la connexion

La commande ci-dessous peut être utilisée pour créer la fonction Edge

    export function PostForm({ onSubmit }: PostFormProps) {
      const [content, setContent] = useState('');
      const [title, setTitle] = useState('');
      const [tags, setTags] = useState<string[]>(['javascript', 'react']);
      const [scheduledTime, setScheduledTime] = useState('');
      const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        onSubmit({ content, title, scheduledTime, tags });
        setContent('');
        setTitle('');
        setScheduledTime('');
        setTags([]);
      };
      const handleTagChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
        const selectedOptions = Array.from(e.target.selectedOptions);
        const selectedTags = selectedOptions.map(option => option.value);
        if(tags.length<4){
    setTags(prevTags => {
          const newTags = selectedTags.filter(tag => !prevTags.includes(tag));
          return [...prevTags, ...newTags];
        });
        }

      };
      const removeTag = (tagToRemove: string) => {
        setTags(tags.filter(tag => tag !== tagToRemove));
      };
      return (
        <form onSubmit={handleSubmit} className="space-y-4 bg-white p-6 rounded-lg shadow-md">
          <div>
            <label htmlFor="title" className="block text-sm font-medium text-gray-700 mb-2">
              Post Title
            </label>
            <input
              type="text"
             >



<p>I will provide the whole code as a GitHub repository at the end. </p>

<p>Now, let’s look at Supbase Integration.</p>

<h2>
  
  
  Supabase
</h2>

<p>First create an account on supabase, if you don’t have one. You can look at this article to get information about the creating an account on Supbase, Using ChatGPT with Your Own Data using LangChain and Supabase.</p>

<p>Create the table scheduled_post. You can use the below SQL code to run in the SQL Editor to create the table or you can create the table with Table Editor.<br>
</p>

<pre class="brush:php;toolbar:false">    create table
      public.scheduled_posts (
        id serial not null,
        content text not null,
        scheduled_time timestamp with time zone not null,
        status text null default 'pending'::text,
        created_at timestamp without time zone null default now(),
        title character varying null,
        devto_article_id character varying null,
        posted_at character varying null,
        tags character varying[] null,
        error_message character varying null,
        constraint scheduled_posts_pkey primary key (id)
      ) tablespace pg_default;
    create index if not exists idx_scheduled_time_status on public.scheduled_posts using btree (scheduled_time, status) tablespace pg_default;
Copier après la connexion

La commande ci-dessus créera un répertoire function/xscheduler dans la supabase. Vous y trouverez l'index.ts. La fonction Edge utilise l'environnement Deno.

Le code ci-dessous concerne la fonction Edge :

    npx supabase init
Copier après la connexion

Pour l'ENV tels que SUPABASE_URL et SUPABASE_SERVICE_ROLE_KEY sont automatiquement disponibles pour vous. Pour DEVTO_ACCESS_TOKEN, vous pouvez le générer à partir d'ici et accéder à Paramètres du projet → Fonctions Edge pour ajouter le jeton. Ce jeton sera disponible dans l'environnement Deno.

Vous pouvez utiliser ce guide pour déployer la fonction Edge, qui est nécessaire.

Tâche Cron

Supbase a récemment mis à jour la fonctionnalité des tâches Cron. Vous pouvez maintenant utiliser le tableau de bord pour créer la tâche de maïs, auparavant vous deviez écrire du code pour cela. Vous pouvez créer une tâche pouvant exécuter les opérations suivantes :

  • Extrait de code SQL
  • Fonction de base de données
  • Demande HTTP
  • Fonction Supbase Edge

Nous allons utiliser la fonction Edge, vous pouvez ajouter les détails de la fonction Edge tels que le nom et l'autorisation avec la clé Anon comme jeton du porteur.

Building a Custom Scheduler Using React and Supabase

Fonctionnement de l'application

Maintenant que nous avons créé l’application, regardons son fonctionnement maintenant. Exécutez le front avec la commande ci-dessous :

    supabase functions new xscheduler
Copier après la connexion

Building a Custom Scheduler Using React and Supabase

Ajoutez les détails tels que le titre, le contenu, l'heure et les balises. Une fois ajouté, cliquez sur Programmer la publication. La tâche cron s'exécutera toutes les minutes une fois que l'heure planifiée de l'article correspond à l'heure actuelle. Il sera publié.

L'article sera publié sur dev.to lorsque la plage horaire correspondra.

Building a Custom Scheduler Using React and Supabase

Fonctionnalités supplémentaires

En utilisant la technique ci-dessus, vous pouvez créer une application de planification pour tout ce qui est tel que X, Instagram, LinkedIn, etc. Vous pouvez travailler dessus et ajouter des fonctionnalités telles que les suivantes :

  • Image : utilisez le stockage supabase pour télécharger et récupérer des images pour les vignettes.
  • Invocation de la fonction Edge à partir de SQL : vous pouvez la rendre encore plus efficace en appelant la fonction Edge à partir d'un extrait de code SQL ou d'une fonction de base de données. Ainsi, ce n'est que lorsque l'article correspond à l'heure actuelle que la fonction Edge est invoquée.

Vous pouvez consulter le code de ce projet sur GitHub ici.

Conclusion

La création d'une application de planification simplifie l'automatisation des tâches telles que la publication d'articles, l'envoi de rappels et la gestion des flux de travail. En utilisant React pour le frontend et Supabase pour le backend, nous avons créé une solution évolutive qui exploite les bases de données, les tâches cron et les fonctions Edge. Cette approche peut être adaptée à différents cas d'utilisation, permettant une automatisation efficace. Avec ces outils, vous êtes équipé pour créer de puissantes applications de planification adaptées à vos besoins.

J'espère que cet article vous a permis de comprendre le travail cron. Merci d'avoir lu l'article.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal