Repository navigation
feat: Add API integrations page and enhance content generation #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| export default function Page(){ | ||
|
|
||
| return( | ||
| <> | ||
| </> | ||
| ) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
components/Layout/Dashboard/Generate/PromptSelector.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| 'use client' | ||
|
|
||
| import React, { useState } from 'react'; | ||
| import { | ||
| Feather, // Placeholder icon for writing | ||
| FileText, | ||
| Rocket, | ||
| Search, | ||
| Zap, | ||
| CheckCircle, | ||
| TrendingUp, | ||
| } from 'lucide-react'; | ||
| import { cn } from '@/lib/utils'; | ||
| import { motion } from 'framer-motion'; | ||
| import { useContent } from '@/context/GenerationContext'; | ||
|
|
||
| // --- Prompt Data Structure --- | ||
| interface Prompt { | ||
| id: string; | ||
| title: string; | ||
| icon: React.ElementType; | ||
| summary: string; | ||
| fullPrompt: string; | ||
| } | ||
|
|
||
| // --- List of Well-Written Prompts --- | ||
| const professionalPrompts: Prompt[] = [ | ||
| { | ||
| id: 'p-1', | ||
| title: 'Executive Summary Generator', | ||
| icon: FileText, | ||
| summary: 'Analyze a 500-word document and extract the three most critical takeaways, summarizing them into a professional executive overview, suitable for C-level review.', | ||
| fullPrompt: 'Analyze the provided text. Identify the three most critical business insights, risks, or opportunities. Summarize these points into a single, concise executive summary paragraph, maintaining a formal and objective tone.', | ||
| }, | ||
| { | ||
| id: 'p-2', | ||
| title: 'SEO-Optimized Blog Post', | ||
| icon: TrendingUp, | ||
| summary: 'Generate a 1000-word blog post on "The Future of Quantum Computing," incorporating a required set of five target keywords naturally throughout the text.', | ||
| fullPrompt: 'Draft a 1000-word SEO-optimized blog post titled "The Future of Quantum Computing." The post must include the following keywords: [quantum entanglement], [superposition], [qubit], [d-wave], and [quantum supremacy]. Structure the post with a compelling introduction, three detailed body sections, and a conclusion with a clear call to action.', | ||
| }, | ||
| { | ||
| id: 'p-3', | ||
| title: 'Competitive Analysis Report', | ||
| icon: Search, | ||
| summary: 'Conduct a high-level competitive analysis of three specified companies, detailing their market position, primary product, and unique selling proposition (USP).', | ||
| fullPrompt: 'Perform a high-level competitive analysis comparing Company A, Company B, and Company C. For each company, detail their current market share (if known), their flagship product, their core technology advantage, and a concise summary of their Unique Selling Proposition (USP). Present the findings in a clear, comparative table format.', | ||
| }, | ||
| { | ||
| id: 'p-4', | ||
| title: 'Viral Social Media Campaign', | ||
| icon: Rocket, | ||
| summary: 'Design a three-part social media campaign (Twitter thread, LinkedIn post, Instagram caption) to promote a new SaaS feature launch.', | ||
| fullPrompt: 'Design a high-impact, three-part social media campaign to promote the launch of a new SaaS feature: "Real-time AI Document Collaboration." Create a compelling, detailed Twitter thread (max 7 tweets), a professional LinkedIn post focused on business value, and a short, engaging Instagram caption with relevant hashtags.', | ||
| }, | ||
| ]; | ||
|
|
||
|
|
||
| export const PromptSelector = () => { | ||
| // State to track the ID of the currently selected prompt | ||
| const [selectedPromptId, setSelectedPromptId] = useState(null); | ||
|
|
||
| const { setPrompt } = useContent(); | ||
|
|
||
| // Derive the full details of the selected prompt | ||
| const selectedPrompt = professionalPrompts.find(p => p.id === selectedPromptId); | ||
|
|
||
| const handleSelect = (id: string, prompt = '') => { | ||
| setSelectedPromptId(id === selectedPromptId ? null : id); | ||
| setPrompt(prompt); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="font-sans p-6 bg-neutral-50 rounded-xl shadow-lg border border-neutral-200"> | ||
| <h2 className="text-2xl font-bold text-neutral-900 mb-2 flex items-center"> | ||
| <Feather className="w-6 h-6 mr-3 text-black" /> | ||
| Prompt Templates Library | ||
| </h2> | ||
| <p className="text-neutral-600 mb-6 border-b pb-3 text-sm"> | ||
| Select a template to instantly load a professionally written prompt into the editor, or use it as inspiration. | ||
| </p> | ||
|
|
||
| {/* Prompt Grid Container (Responsive Layout) */} | ||
| <div className="grid grid-cols-1 gap-4 sm:grid-cols-1 lg:grid-cols-2"> | ||
| {professionalPrompts.map((prompt) => { | ||
| const isSelected = prompt.id === selectedPromptId; | ||
| const IconComponent = prompt.icon; | ||
|
|
||
| return ( | ||
| <motion.div | ||
| key={prompt.id} | ||
| initial={{ scale: 1 }} | ||
| whileHover={{ scale: 1.01, zIndex: 10 }} | ||
| onClick={() => handleSelect(prompt.id, prompt.fullPrompt)} | ||
| className={cn( | ||
| 'group p-4 rounded-xl border-2 transition-300 cursor-pointer shadow-sm', | ||
| 'flex flex-col justify-between min-h-[180px]', | ||
| // Default state | ||
| 'bg-white border-neutral-200 hover:border-black/50 hover:shadow-md', | ||
| // Selected state | ||
| isSelected | ||
| ? 'border-black bg-black text-white shadow-xl ring-2 ring-offset-2 ring-black/50' | ||
| : 'text-neutral-900', | ||
| )} | ||
| > | ||
| <div className="mb-4"> | ||
| <div className={cn( | ||
| 'p-2 rounded-full mb-3 inline-block transition-colors duration-300', | ||
| isSelected | ||
| ? 'bg-white text-black' | ||
| : 'bg-neutral-100 text-neutral-700 group-hover:bg-black group-hover:text-white', | ||
| )}> | ||
| <IconComponent className="w-5 h-5" /> | ||
| </div> | ||
| <h3 className={cn( | ||
| "text-lg font-semibold", | ||
| isSelected ? 'text-white' : 'text-neutral-900 group-hover:text-black' | ||
| )}> | ||
| {prompt.title} | ||
| </h3> | ||
| </div> | ||
|
|
||
| <div className="text-xs opacity-90"> | ||
| <p className={cn( | ||
| "line-clamp-3", | ||
| isSelected ? 'text-neutral-300' : 'text-neutral-600 group-hover:text-neutral-800' | ||
| )}>{prompt.summary}</p> | ||
| </div> | ||
|
|
||
| {isSelected && ( | ||
| <div className="mt-3 flex items-center text-xs font-semibold text-white"> | ||
| <CheckCircle className="w-4 h-4 mr-1.5" /> Selected | ||
| </div> | ||
| )} | ||
| </motion.div> | ||
| ); | ||
| })} | ||
| </div> | ||
|
|
||
| {/*/!* Selected Prompt Display (for demonstration) *!/*/} | ||
| {/*{selectedPrompt && (*/} | ||
| {/* <motion.div*/} | ||
| {/* initial={{ opacity: 0, y: 20 }}*/} | ||
| {/* animate={{ opacity: 1, y: 0 }}*/} | ||
| {/* className="mt-8 p-5 bg-black rounded-xl shadow-xl border border-neutral-700"*/} | ||
| {/* >*/} | ||
| {/* <h3 className="flex items-center text-lg font-bold text-white mb-2">*/} | ||
| {/* <Zap className="w-5 h-5 mr-2 text-yellow-400" />*/} | ||
| {/* Active Prompt Text*/} | ||
| {/* </h3>*/} | ||
| {/* <p className="font-mono text-sm text-neutral-300 whitespace-pre-wrap">*/} | ||
| {/* {selectedPrompt.fullPrompt}*/} | ||
| {/* </p>*/} | ||
| {/* <p className="mt-4 text-xs text-neutral-500">*/} | ||
| {/* *This text is now ready to be loaded into your main input field.**/} | ||
| {/* </p>*/} | ||
| {/* </motion.div>*/} | ||
| {/*)}*/} | ||
| </div> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check failure
Code scanning / CodeQL
Server-side request forgery Critical
Copilot Autofix
AI 11 months ago
To address SSRF, you must restrict which URLs can be targeted by requests made through
makeRequest. The safest approach is to maintain an allowlist (whitelist) of permitted hostnames or base URLs. Instead of allowing arbitrary URL input, you should use a lookup mechanism: callers pass an identifier (e.g.,"serviceA","serviceB") or choose from a list, and the actual URL used for the request is determined by a secure mapping in the server code.urlparameter in requests with a system that validates or selects URLs from an allowlist before making the request.makeRequest. Have the function consult this mapping, and use only values from it—never raw user input as the request destination. Validate input against this mapping and throw an error if the supplied identifier or URL isn't allowed.makeRequestinlib/actions/content.actions.ts.