Heim > Web-Frontend > js-Tutorial > Erstellen eines benutzerdefinierten Schedulers mit React und Supabase

Erstellen eines benutzerdefinierten Schedulers mit React und Supabase

Susan Sarandon
Freigeben: 2024-12-18 07:08:15
Original
301 Leute haben es durchsucht

Einführung

Planung ist eines der entscheidenden Merkmale moderner Anwendungen. Es kann uns ermöglichen, regelmäßige Aufgaben auszuführen, die automatisiert werden können. Aufgaben wie das Versenden von Erinnerungen, das Planen von Beiträgen, das Aktualisieren von Daten oder das Automatisieren von Arbeitsabläufen.

In diesem Artikel werden wir einen Planer für die Veröffentlichung von Artikeln auf dev.to erstellen. Obwohl dev.to über Planungsfunktionen verfügt, werden wir sie auf unsere Weise implementieren, die zum Erstellen jeder Art von Planungsanwendung verwendet werden kann.

Also, fangen wir an.

Tech-Stack

Wir werden den folgenden Tech-Stack verwenden:

  • Reagieren: Wir werden React verwenden, insbesondere ViteJS mit React, um das Fronted zu erstellen.
  • Supabase: Es bietet eine Komplettlösung für die Erstellung von Anwendungen. Es bietet eine Datenbank, Authentifizierung, Speicher, Edge-Funktion und vieles mehr. Wir werden Folgendes von Supbase verwenden:
    • Datenbank: Hier werden die Artikelinformationen und die Terminplanung gespeichert.
    • Cron-Job: Zur regelmäßigen Ausführung, um die Edge-Funktion aufzurufen
    • Edge-Funktion: Dadurch wird überprüft, ob für einen Artikel die aktuelle Zeit als geplante Zeit festgelegt ist. Wenn dann, wird der Artikel veröffentlicht.

Das wird ausreichen, um problemlos eine Zeitplaneranwendung zu erstellen.

Arbeiten an der Bewerbung

Lassen Sie uns besprechen, wie die Anwendung funktioniert, wodurch es recht einfach wird, den Ablauf der Anwendung zu verstehen. Hier ist der Ablauf nacheinander:

  1. Artikel über das Frontend zur Datenbank hinzufügen.
  2. Der Cron-Job wird jede Minute ausgeführt, um die Edge-Funktion aufzurufen.
  3. Eine Randfunktion wird ausgeführt, um die aktuelle Zeit als geplanten Artikel zu überprüfen. Wenn es einen Artikel gibt, wird der Artikel veröffentlicht.
  4. Artikeldaten in der Beitragstabelle werden aktualisiert. # Aufbau des Frontends

Das Gebäude-Frontend ist in letzter Zeit ruhig geworden, da viel generative KI zum Einsatz kommt. Eine dieser KIs, die wir verwenden werden, ist Bolt.new. Warum Bolt.new? Es kann vollständige React-Anwendungen mit Abhängigkeiten und allen Konfigurationen wie tailwindcss generieren. Sie können Artikel direkt mit StackBlitz bearbeiten und die Anwendung auch bereitstellen. Bei Bedarf können Sie den Code herunterladen, um ihn lokal auszuführen. Der Bonuspunkt ist, dass es sich recht gut in Supabase integrieren lässt, sodass Sie mit der Supbase-Integration eine funktionierende React-Anwendung generieren können.

Ich habe es verwendet, um die Front zu generieren. Hier sind alle Seiten.

App.tsx

Dadurch wird die Seite für die Anzeige von Komponenten und die Bereitstellung der Zielseite verwaltet.

    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;
Nach dem Login kopieren
Nach dem Login kopieren

SchudledPost.tsx

Hier werden die geplanten Artikel angezeigt.

    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>
      );
    }
Nach dem Login kopieren
Nach dem Login kopieren

PostForm.tsx

Hiermit wird das Formular verwaltet, in dem der Benutzer Informationen zum Artikel angeben kann.

    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;
Nach dem Login kopieren
Nach dem Login kopieren

Kantenfunktion

Edge-Funktionen sind serverseitige TypeScript-Funktionen, die global am Edge verteilt werden – in der Nähe Ihrer Benutzer. Sie können zum Abhören von Webhooks oder zur Integration Ihres Supabase-Projekts mit Drittanbietern wie Stripe verwendet werden. Kantenfunktionen werden mit Deno entwickelt.

Um die Edge-Funktion lokal ausführen und bereitstellen zu können, benötigen Sie Folgendes:

  • Supbase CLI: Mit dieser Anleitung können Sie CLI lokal installieren. Es ist ganz einfach, einfach npm und npx zu verwenden.
  • Docker Desktop: Installieren Sie den Docker-Desktop von hier aus.

Nach der Installation können Sie also Ihr Frontend-Codeverzeichnis oder ein anderes verwenden, um die Supabase Edge-Funktion zu erstellen.

Führen Sie den folgenden Befehl aus, um ein Supabase-Projekt zu starten:

    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>
      );
    }
Nach dem Login kopieren
Nach dem Login kopieren

Mit dem folgenden Befehl kann die Edge-Funktion erstellt werden

    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;
Nach dem Login kopieren

Der obige Befehl erstellt ein Verzeichnis „functions/xscheduler“ innerhalb der Supabase. Dort finden Sie die index.ts. Die Edge-Funktion nutzt die Deno-Umgebung.

Der folgende Code gilt für die Kantenfunktion:

    npx supabase init
Nach dem Login kopieren

Für die ENV stehen Ihnen automatisch SUPABASE_URL und SUPABASE_SERVICE_ROLE_KEY zur Verfügung. Für DEVTO_ACCESS_TOKEN können Sie es hier generieren und zu Projekteinstellungen → Kantenfunktionen gehen, um das Token hinzuzufügen. Dieser Token wird in der Deno-Umgebung verfügbar sein.

Sie können diese Anleitung für die Bereitstellung der benötigten Edge-Funktion verwenden.

Cron-Job

Supbase hat kürzlich die Cron-Job-Funktionalität aktualisiert. Jetzt können Sie das Dashboard verwenden, um den Maisjob zu erstellen, zuvor mussten Sie dafür Code schreiben. Sie können einen Job erstellen, der Folgendes ausführen kann:

  • SQL-Snippet
  • Datenbankfunktion
  • HTTP-Anfrage
  • Supbase-Kantenfunktion

Wir werden die Edge-Funktion verwenden. Sie können die Details der Edge-Funktion wie Name und Autorisierung mit dem Anon-Schlüssel als Bearer-Token hinzufügen.

Building a Custom Scheduler Using React and Supabase

Funktionsweise der Anwendung

Da wir nun die Anwendung erstellt haben, werfen wir einen Blick auf die Funktionsweise. Führen Sie fronted mit dem folgenden Befehl aus:

    supabase functions new xscheduler
Nach dem Login kopieren

Building a Custom Scheduler Using React and Supabase

Fügen Sie Details wie Titel, Inhalt, Zeit und Tags hinzu. Klicken Sie nach dem Hinzufügen auf „Beitrag planen“. Der Cron-Job wird jede Minute ausgeführt, sobald die geplante Zeit des Artikels mit der aktuellen Zeit übereinstimmt. Es wird veröffentlicht.

Der Artikel wird auf dev.to veröffentlicht, wenn der Zeitraum übereinstimmt.

Building a Custom Scheduler Using React and Supabase

Zusätzliche Funktionen

Mit der oben genannten Technik können Sie eine Planungsanwendung für alles wie X, Instagram, LinkedIn usw. erstellen. Sie können daran arbeiten und Funktionen wie die folgenden hinzufügen:

  • Bild: Verwenden Sie den Supabase-Speicher, um Bilder für Miniaturansichten hochzuladen und abzurufen.
  • Edge-Funktionsaufruf aus SQL: Sie können es noch effizienter gestalten, indem Sie die Edge-Funktion aus einem SQL-Snippet oder einer Datenbankfunktion aufrufen. Dadurch wird die Kantenfunktion nur dann aufgerufen, wenn der Artikel mit der aktuellen Zeit übereinstimmt.

Sie können sich den Code dieses Projekts hier auf GitHub ansehen.

Abschluss

Das Erstellen einer Planeranwendung vereinfacht die Automatisierung von Aufgaben wie dem Veröffentlichen von Artikeln, dem Versenden von Erinnerungen und dem Verwalten von Arbeitsabläufen. Mit React für das Frontend und Supabase für das Backend haben wir eine skalierbare Lösung erstellt, die Datenbanken, Cron-Jobs und Edge-Funktionen nutzt. Dieser Ansatz kann für verschiedene Anwendungsfälle angepasst werden und ermöglicht so eine effiziente Automatisierung. Mit diesen Tools sind Sie in der Lage, leistungsstarke Planungsanwendungen zu erstellen, die auf Ihre Bedürfnisse zugeschnitten sind.

Ich hoffe, dieser Artikel hat Ihnen ein Verständnis für den Cron-Job vermittelt. Vielen Dank, dass Sie den Artikel gelesen haben.

Das obige ist der detaillierte Inhalt vonErstellen eines benutzerdefinierten Schedulers mit React und Supabase. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage