mirror of
https://github.com/appwrite/appwrite
synced 2026-05-22 00:18:25 +00:00
Merge pull request #10031 from appwrite/chore-add-new-site-templates
Add formspree and react-admin templates to sites
This commit is contained in:
commit
cd8e93db60
6 changed files with 192 additions and 10 deletions
|
|
@ -22,6 +22,8 @@ class UseCases
|
|||
public const DOCUMENTATION = 'documentation';
|
||||
public const BLOG = 'blog';
|
||||
public const AI = 'artificial intelligence';
|
||||
public const FORMS = 'forms';
|
||||
public const DASHBOARD = 'dashboard';
|
||||
}
|
||||
|
||||
const TEMPLATE_FRAMEWORKS = [
|
||||
|
|
@ -1469,4 +1471,135 @@ return [
|
|||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'key' => 'crm-dashboard-react-admin',
|
||||
'name' => 'CRM dashboard with React Admin',
|
||||
'tagline' => 'A React-based admin dashboard template with CRM features.',
|
||||
'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'useCases' => [UseCases::DASHBOARD],
|
||||
'screenshotDark' => $url . '/images/sites/templates/crm-dashboard-react-admin-dark.png',
|
||||
'screenshotLight' => $url . '/images/sites/templates/crm-dashboard-react-admin-light.png',
|
||||
'frameworks' => [
|
||||
getFramework('REACT', [
|
||||
'providerRootDirectory' => './react/react-admin',
|
||||
'installCommand' => 'pnpm install',
|
||||
'buildCommand' => 'pnpm build && pnpm db-seed',
|
||||
'outputDirectory' => './dist',
|
||||
]),
|
||||
],
|
||||
'vcsProvider' => 'github',
|
||||
'providerRepositoryId' => 'templates-for-sites',
|
||||
'providerOwner' => 'appwrite',
|
||||
'providerVersion' => '0.7.*',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_ENDPOINT',
|
||||
'description' => 'Endpoint of Appwrite server',
|
||||
'value' => '{apiEndpoint}',
|
||||
'placeholder' => '{apiEndpoint}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_PROJECT_ID',
|
||||
'description' => 'Your Appwrite project ID',
|
||||
'value' => '{projectId}',
|
||||
'placeholder' => '{projectId}',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'APPWRITE_API_KEY',
|
||||
'description' => 'Your Appwrite API key (for seeding only)',
|
||||
'value' => '',
|
||||
'placeholder' => 'a0b1...',
|
||||
'required' => true,
|
||||
'type' => 'password'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_DATABASE_ID',
|
||||
'description' => 'Database ID (default: admin)',
|
||||
'value' => 'admin',
|
||||
'placeholder' => 'admin',
|
||||
'required' => false,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_TABLE_REVIEWS',
|
||||
'description' => 'Table ID for reviews table',
|
||||
'value' => 'reviews',
|
||||
'placeholder' => 'reviews',
|
||||
'required' => false,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_TABLE_INVOICES',
|
||||
'description' => 'Table ID for invoices table',
|
||||
'value' => 'invoices',
|
||||
'placeholder' => 'invoices',
|
||||
'required' => false,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_TABLE_ORDERS',
|
||||
'description' => 'Table ID for orders table',
|
||||
'value' => 'orders',
|
||||
'placeholder' => 'orders',
|
||||
'required' => false,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_TABLE_PRODUCTS',
|
||||
'description' => 'Table ID for products table',
|
||||
'value' => 'products',
|
||||
'placeholder' => 'products',
|
||||
'required' => false,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_TABLE_CATEGORIES',
|
||||
'description' => 'Table ID for categories table',
|
||||
'value' => 'categories',
|
||||
'placeholder' => 'categories',
|
||||
'required' => false,
|
||||
'type' => 'text'
|
||||
],
|
||||
[
|
||||
'name' => 'VITE_APPWRITE_TABLE_CUSTOMERS',
|
||||
'description' => 'Table ID for customers table',
|
||||
'value' => 'customers',
|
||||
'placeholder' => 'customers',
|
||||
'required' => false,
|
||||
'type' => 'text'
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'key' => 'job-applications-formspree',
|
||||
'name' => 'Job applications form with Formspree',
|
||||
'tagline' => 'A simple form submission template using Formspree.',
|
||||
'score' => 4, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'useCases' => [UseCases::FORMS],
|
||||
'screenshotDark' => $url . '/images/sites/templates/job-applications-formspree-dark.png',
|
||||
'screenshotLight' => $url . '/images/sites/templates/job-applications-formspree-light.png',
|
||||
'frameworks' => [
|
||||
getFramework('REACT', [
|
||||
'providerRootDirectory' => './react/formspree',
|
||||
]),
|
||||
],
|
||||
'vcsProvider' => 'github',
|
||||
'providerRepositoryId' => 'templates-for-sites',
|
||||
'providerOwner' => 'appwrite',
|
||||
'providerVersion' => '0.7.*',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => 'VITE_FORMSPREE_FORM_ID',
|
||||
'description' => 'Your Formspree form ID',
|
||||
'value' => '',
|
||||
'placeholder' => 'xrgkpqld',
|
||||
'required' => true,
|
||||
'type' => 'text'
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
|
|||
BIN
public/images/sites/templates/crm-dashboard-react-admin-dark.png
Normal file
BIN
public/images/sites/templates/crm-dashboard-react-admin-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -3,6 +3,7 @@
|
|||
namespace Appwrite\Platform\Tasks;
|
||||
|
||||
// Example usage: docker compose exec appwrite screenshot --templateId="playground-for-tanstack-start"
|
||||
// Example of env vars flag: --variables="{\"VITE_FORMSPREE_FORM_ID\":\"xvgkbzll\", \"VITE_FORMSPREE_FORM_SECRET\":\"some_secret\"}"
|
||||
// Expected output: public/images/sites/templates/playground-for-tanstack-start-light.png (and dark.png)
|
||||
|
||||
use Appwrite\ID;
|
||||
|
|
@ -10,6 +11,7 @@ use Tests\E2E\Client;
|
|||
use Utopia\CLI\Console;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
class Screenshot extends Action
|
||||
|
|
@ -24,11 +26,24 @@ class Screenshot extends Action
|
|||
$this
|
||||
->desc('Create Site template screenshot')
|
||||
->param('templateId', '', new Text(128), 'Template ID.')
|
||||
->param('variables', '', new Text(16384), 'JSON of env variables to use when setting up the site.')
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(string $templateId): void
|
||||
public function action(string $templateId, string $variables): void
|
||||
{
|
||||
if (empty($variables)) {
|
||||
$variables = [];
|
||||
} else {
|
||||
$variables = \json_decode($variables, true);
|
||||
if (!\is_array($variables)) {
|
||||
throw new \Exception('Invalid JSON in --variables flag');
|
||||
}
|
||||
}
|
||||
if ($variables === null) {
|
||||
throw new \Exception('Invalid JSON in --variables flag');
|
||||
}
|
||||
|
||||
$templates = Config::getParam('templates-site', []);
|
||||
|
||||
$allowedTemplates = \array_filter($templates, function ($item) use ($templateId) {
|
||||
|
|
@ -133,6 +148,11 @@ class Screenshot extends Action
|
|||
|
||||
$framework = $template['frameworks'][0];
|
||||
|
||||
// Use best specifications to prevent out-of-memory during build
|
||||
$specifications = Config::getParam('specifications', []);
|
||||
$specifications = array_keys($specifications);
|
||||
$specification = \end($specifications);
|
||||
|
||||
// Create site
|
||||
$site = $client->call(Client::METHOD_POST, '/sites', [
|
||||
'content-type' => 'application/json',
|
||||
|
|
@ -141,6 +161,7 @@ class Screenshot extends Action
|
|||
'cookie' => $cookieConsole
|
||||
], [
|
||||
'siteId' => ID::unique(),
|
||||
'specification' => $specification,
|
||||
'name' => $template["name"],
|
||||
'framework' => $framework['key'],
|
||||
'adapter' => $framework['adapter'],
|
||||
|
|
@ -162,21 +183,48 @@ class Screenshot extends Action
|
|||
|
||||
$siteId = $site['body']['$id'];
|
||||
|
||||
// Prepare API key, incase it's needed as variable
|
||||
$response = $client->call(Client::METHOD_POST, '/projects/' . $projectId . '/keys', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => 'console',
|
||||
'cookie' => $cookieConsole
|
||||
], [
|
||||
'name' => 'Screenshot API key',
|
||||
'scopes' => \array_keys(Config::getParam('scopes', []))
|
||||
]);
|
||||
|
||||
if ($response['headers']['status-code'] !== 201) {
|
||||
Console::error(\json_encode($response));
|
||||
throw new \Exception("Failed to create API key");
|
||||
}
|
||||
|
||||
$apiKey = $response['body']['secret'];
|
||||
|
||||
Console::info("API key created");
|
||||
|
||||
$variables['APPWRITE_API_KEY'] = $apiKey;
|
||||
|
||||
// Create variables
|
||||
if (!empty($template['variables'] ?? [])) {
|
||||
foreach ($template['variables'] as $variable) {
|
||||
if (empty($variable['value'] ?? '')) {
|
||||
if (($variable['required'] ?? false) === true) {
|
||||
throw new \Exception("Missing required variable: {$variable['name']}");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
$name = $variable['name'];
|
||||
|
||||
$value = $variable['value'];
|
||||
$value = \str_replace('{projectName}', $projectName, $value);
|
||||
$value = \str_replace('{projectId}', $projectId, $value);
|
||||
$value = \str_replace('{apiEndpoint}', 'http://localhost/v1', $value);
|
||||
$value = \str_replace('{apiEndpoint}', 'http://' . System::getEnv('_APP_DOMAIN', '') . '/v1', $value);
|
||||
|
||||
if (\array_key_exists($name, $variables)) {
|
||||
$value = $variables[$name];
|
||||
}
|
||||
|
||||
if (empty($value)) {
|
||||
if (($variable['required'] ?? false) === true) {
|
||||
throw new \Exception("Missing required variable: {$variable['name']}. Provide it using the --variables flag to resolve this.");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$response = $client->call(Client::METHOD_POST, '/sites/' . $siteId . '/variables', [
|
||||
'content-type' => 'application/json',
|
||||
|
|
@ -207,7 +255,8 @@ class Screenshot extends Action
|
|||
'owner' => $template['providerOwner'],
|
||||
'repository' => $template['providerRepositoryId'],
|
||||
'rootDirectory' => $framework['providerRootDirectory'],
|
||||
'version' => $template['providerVersion'],
|
||||
'reference' => $template['providerVersion'],
|
||||
'type' => 'tag',
|
||||
'activate' => true,
|
||||
]);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue