Skip to content

Next #234

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

Open
wants to merge 68 commits into
base: main
Choose a base branch
from
Open

Next #234

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
e1d9113
fix: Support both single function and array for beforeLoginConfirmation
SerVitasik Jun 13, 2025
12b1217
feat: add custom filter component for square meters and integrate int…
NoOne7135 Jun 16, 2025
8380ce0
remove vue-suggestion-input dependency
SerVitasik Jun 23, 2025
cbabda7
docs: update RichEditor and Markdown plugin documentation with new re…
NoOne7135 Jun 23, 2025
41855c9
fix: increase limit for column options from 1000 to 1250
SerVitasik Jun 24, 2025
370b536
fix: increase limit for column options from 1250 to 10000
SerVitasik Jun 24, 2025
cc6dd90
Revert "feat: add support for opening list item link in new tab on mi…
SerVitasik Jun 24, 2025
230da5a
fix: revert "feat: add support for opening list item link in new tab …
SerVitasik Jun 24, 2025
3b9c25f
docs: add diff-add comment in markdown plugin tutorial for clarity
NoOne7135 Jun 24, 2025
554a351
feat: refactor square meters filter buttons to use dynamic options an…
NoOne7135 Jun 24, 2025
69a1829
docs: update migration command in getting started tutorial for clarity
Romper9 Jun 25, 2025
5b4aeef
normalize beforeLoginConfirmation to support both single function and…
SerVitasik Jun 27, 2025
3154f1a
fix: cross platform support for postinstall
SerVitasik Jun 30, 2025
d68be08
fix: cross platform support for postinstall
SerVitasik Jun 30, 2025
dbc3eea
fix: cross platform support for postinstall
SerVitasik Jun 30, 2025
0145df2
fix: cross platform support for postinstall
SerVitasik Jun 30, 2025
41f4403
fix: cross platform support for postinstall
SerVitasik Jun 30, 2025
3d9e95b
fix: improve cross-platform compatibility for dependency installation…
SerVitasik Jun 30, 2025
791c3e3
fix: enhance cross-platform compatibility for npm dependency installa…
SerVitasik Jul 1, 2025
3389a2a
fix: update adminforth dependency version to 'next' for improved comp…
SerVitasik Jul 1, 2025
0c5c808
fix: enhance cross-platform compatibility in currentFileDir function
SerVitasik Jul 2, 2025
cfcf80a
fix: enhance cross-platform compatibility for temp directory and comm…
SerVitasik Jul 2, 2025
668417d
fix: add detailed debug logging for AdminForth and CodeInjector initi…
SerVitasik Jul 2, 2025
e449f95
fix: improve cross-platform compatibility for script execution in ind…
SerVitasik Jul 2, 2025
e0e5038
fix: streamline code and enhance cross-platform compatibility in Code…
SerVitasik Jul 2, 2025
3706caf
fix: improve cross-platform compatibility for npm execution in CodeIn…
SerVitasik Jul 2, 2025
6f5a65e
fix: refine cross-platform compatibility for script execution in inde…
SerVitasik Jul 2, 2025
fb0df18
fix: enhance cross-platform command execution in CodeInjector by refi…
SerVitasik Jul 2, 2025
c7b9201
fix: refine i18n extraction command for improved cross-platform compa…
SerVitasik Jul 3, 2025
18b9918
fix: improve npm execution logic for better Windows compatibility in …
SerVitasik Jul 3, 2025
fb5855a
Merge pull request #227 from devforth/custom-filter-component
ivictbor Jul 3, 2025
2ebd9b6
Merge pull request #224 from devforth/beforeLoginConfirmation-fix
ivictbor Jul 3, 2025
448c928
fix: update adminforth dependency version to latest in package.json t…
SerVitasik Jul 3, 2025
41d7f8a
Merge branch 'next' of github.com:devforth/adminforth into next
SerVitasik Jul 3, 2025
259cecc
Merge branch 'main' of github.com:devforth/adminforth into next
ivictbor Jul 3, 2025
ca9ef12
Merge branch 'next' of github.com:devforth/adminforth into next
SerVitasik Jul 3, 2025
25276f5
Merge branch 'main' of github.com:devforth/adminforth into next
SerVitasik Jul 3, 2025
9084bd0
fix: simplify file path comparison in index.ts.hbs
SerVitasik Jul 3, 2025
ca9aa9c
fix: update npm command execution to use node binary and change admin…
SerVitasik Jul 3, 2025
23a215d
fix: add console log for npm command execution path to test on Windows
SerVitasik Jul 3, 2025
9188e21
docs: escape < and > in custom filter example to fix MDX build error
NoOne7135 Jul 3, 2025
4175e6c
fix: quote paths in npm command execution to handle spaces in Windows…
SerVitasik Jul 3, 2025
1472d75
Merge branch 'next' of github.com:devforth/adminforth into next
SerVitasik Jul 3, 2025
478e3ec
fix: refactor npm dependency installation to streamline command execu…
SerVitasik Jul 3, 2025
0368f21
fix: update adminforth dependency version in package.json template fr…
SerVitasik Jul 3, 2025
c73dcb0
docs: update migration command in gettingStarted.md to include local …
SerVitasik Jul 3, 2025
ce84b0f
fix: enhance npm command execution for Windows compatibility by using…
SerVitasik Jul 3, 2025
109ef9b
docs: update migration commands to include local migration execution
NoOne7135 Jul 3, 2025
57df6de
Merge branch 'next' of https://github.com/devforth/adminforth into next
NoOne7135 Jul 3, 2025
c2b6bff
docs: add onMounted lifecycle hook to custom field rendering tutorial
NoOne7135 Jul 3, 2025
f00e37c
fix: adjust Dropzone component styles for better file upload handling…
SerVitasik Jul 3, 2025
5a330c6
Merge branch 'next' of github.com:devforth/adminforth into next
SerVitasik Jul 3, 2025
2890979
docs: add Twitch adapter installation and configuration instructions
NoOne7135 Jul 3, 2025
aaae67e
add Twitch OAuth2 adapter to dev-demo
NoOne7135 Jul 3, 2025
5f23cea
Merge pull request #235 from devforth/twitch-oauth-adapter
ivictbor Jul 3, 2025
9911a67
add Twitch OAuth adapter to the installation script
NoOne7135 Jul 4, 2025
30def17
feat: add overInputs injection point to login page
SerVitasik Jul 4, 2025
37762f8
replace overInputs with panelHeader in login page injection configura…
SerVitasik Jul 4, 2025
a386a8e
Merge pull request #236 from devforth/loginPageInjection
ivictbor Jul 4, 2025
55639f5
fix: add classes for custom styling in LoginView
SerVitasik Jul 4, 2025
dd89ff3
feat: enhance Input component with custom styling and right icon slot
SerVitasik Jul 4, 2025
9165328
feat: add custom classes to UI components for consistent styling
SerVitasik Jul 4, 2025
c57d115
docs: add Mailgun setup instructions and configuration details
NoOne7135 Jul 4, 2025
4ee2cbd
fix: update LoginView to use template for conditional rendering of pa…
SerVitasik Jul 4, 2025
a951ee5
add Mailgun email adapter to the installation script
NoOne7135 Jul 4, 2025
b8ffdf9
fix: bind username and password inputs to reactive variables in Login…
SerVitasik Jul 4, 2025
ca4d009
add docs to input right icon
SerVitasik Jul 4, 2025
058ab54
Merge pull request #237 from devforth/mailgun-email-adapter
ivictbor Jul 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion adapters/install-adapters.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
ADAPTERS="adminforth-completion-adapter-open-ai-chat-gpt adminforth-email-adapter-aws-ses adminforth-google-oauth-adapter adminforth-github-oauth-adapter adminforth-facebook-oauth-adapter adminforth-keycloak-oauth-adapter adminforth-microsoft-oauth-adapter adminforth-image-generation-adapter-openai adminforth-storage-adapter-amazon-s3 adminforth-storage-adapter-local"
ADAPTERS="adminforth-completion-adapter-open-ai-chat-gpt adminforth-email-adapter-aws-ses adminforth-email-adapter-mailgun adminforth-google-oauth-adapter adminforth-github-oauth-adapter adminforth-facebook-oauth-adapter adminforth-keycloak-oauth-adapter adminforth-microsoft-oauth-adapter adminforth-twitch-oauth-adapter adminforth-image-generation-adapter-openai adminforth-storage-adapter-amazon-s3 adminforth-storage-adapter-local"

# for each
install_adapter() {
Expand Down
4 changes: 3 additions & 1 deletion adminforth/commands/createApp/templates/index.ts.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import express from 'express';
import AdminForth from 'adminforth';
import usersResource from "./resources/adminuser.js";
import { fileURLToPath } from 'url';
import path from 'path';

const ADMIN_BASE_URL = '';

Expand Down Expand Up @@ -55,7 +57,7 @@ export const admin = new AdminForth({
],
});

if (import.meta.url === `file://${process.argv[1]}`) {
if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
const app = express();
app.use(express.json());

Expand Down
20 changes: 14 additions & 6 deletions adminforth/commands/createApp/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,22 @@ async function writeTemplateFiles(dirname, cwd, options) {
}

async function installDependencies(ctx, cwd) {
const nodeBinary = process.execPath; // Path to the Node.js binary running this script
const npmPath = path.join(path.dirname(nodeBinary), 'npm'); // Path to the npm executable
const isWindows = process.platform === 'win32';

const nodeBinary = process.execPath;
const npmPath = path.join(path.dirname(nodeBinary), 'npm');
const customDir = ctx.customDir;
const res = await Promise.all([
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd, env: { PATH: process.env.PATH } }),
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
]);
if (isWindows) {
const res = await Promise.all([
await execAsync(`npm install`, { cwd, env: { PATH: process.env.PATH } }),
await execAsync(`npm install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
]);
} else {
const res = await Promise.all([
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd, env: { PATH: process.env.PATH } }),
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
]);
}
// console.log(chalk.dim(`Dependencies installed in ${cwd} and ${customDir}: \n${res[0].stdout}${res[1].stdout}`));
}

Expand Down
46 changes: 25 additions & 21 deletions adminforth/commands/createCustomComponent/configUpdater.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export async function updateResourceConfig(resourceId, columnName, fieldType, co
}


export async function injectLoginComponent(indexFilePath, componentPath) {
export async function injectLoginComponent(indexFilePath, componentPath, injectionType) {
console.log(chalk.dim(`Reading file: ${indexFilePath}`));
const content = await fs.readFile(indexFilePath, 'utf-8');
const ast = recast.parse(content, {
Expand All @@ -263,6 +263,7 @@ export async function injectLoginComponent(indexFilePath, componentPath) {

let updated = false;
let injectionLine = null;
let targetProperty = null;

recast.visit(ast, {
visitNewExpression(path) {
Expand Down Expand Up @@ -293,20 +294,23 @@ export async function injectLoginComponent(indexFilePath, componentPath) {
const loginPageInjections = getOrCreateProp(customization, 'loginPageInjections');
if (!n.ObjectExpression.check(loginPageInjections)) return false;

let underInputsProp = loginPageInjections.properties.find(
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === 'underInputs'
// Determine target property based on injection type
targetProperty = injectionType === 'beforeLogin' ? 'panelHeader' : 'underInputs';

let targetProp = loginPageInjections.properties.find(
p => n.ObjectProperty.check(p) && n.Identifier.check(p.key) && p.key.name === targetProperty
);

if (underInputsProp) {
const currentVal = underInputsProp.value;
injectionLine = underInputsProp.loc?.start.line ?? null;
if (targetProp) {
const currentVal = targetProp.value;
injectionLine = targetProp.loc?.start.line ?? null;
if (n.StringLiteral.check(currentVal)) {
if (currentVal.value !== componentPath) {
underInputsProp.value = b.arrayExpression([
targetProp.value = b.arrayExpression([
b.stringLiteral(currentVal.value),
b.stringLiteral(componentPath),
]);
console.log(chalk.dim(`Converted 'underInputs' to array with existing + new path.`));
console.log(chalk.dim(`Converted '${targetProperty}' to array with existing + new path.`));
} else {
console.log(chalk.dim(`Component path already present as string. Skipping.`));
}
Expand All @@ -316,26 +320,26 @@ export async function injectLoginComponent(indexFilePath, componentPath) {
);
if (!exists) {
currentVal.elements.push(b.stringLiteral(componentPath));
console.log(chalk.dim(`Appended new component path to existing 'underInputs' array.`));
console.log(chalk.dim(`Appended new component path to existing '${targetProperty}' array.`));
} else {
console.log(chalk.dim(`Component path already present in array. Skipping.`));
}
} else {
console.warn(chalk.yellow(`⚠️ 'underInputs' is not a string or array. Skipping.`));
console.warn(chalk.yellow(`⚠️ '${targetProperty}' is not a string or array. Skipping.`));
return false;
}
} else {
const newProperty = b.objectProperty(
b.identifier('underInputs'),
b.stringLiteral(componentPath)
);
if (newProperty.loc) {
console.log(chalk.dim(`Adding 'underInputs' at line: ${newProperty.loc.start.line}`));
}
loginPageInjections.properties.push(newProperty);
console.log(chalk.dim(`Added 'underInputs': ${componentPath}`));
b.identifier(targetProperty),
b.stringLiteral(componentPath)
);

if (newProperty.loc) {
console.log(chalk.dim(`Adding '${targetProperty}' at line: ${newProperty.loc.start.line}`));
}

loginPageInjections.properties.push(newProperty);
console.log(chalk.dim(`Added '${targetProperty}': ${componentPath}`));
}

updated = true;
Expand All @@ -353,7 +357,7 @@ export async function injectLoginComponent(indexFilePath, componentPath) {
await fs.writeFile(indexFilePath, outputCode, 'utf-8');
console.log(
chalk.green(
`✅ Successfully updated CRUD injection in resource file: ${indexFilePath}` +
`✅ Successfully updated login ${targetProperty} injection in: ${indexFilePath}` +
(injectionLine !== null ? `:${injectionLine}` : '')
)
);
Expand Down
2 changes: 1 addition & 1 deletion adminforth/commands/createCustomComponent/fileGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export async function generateLoginOrGlobalComponentFile(componentFileName, inje
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
let templatePath;
if (injectionType === 'afterLogin') {
if (injectionType === 'afterLogin' || injectionType === 'beforeLogin') {
templatePath = path.join(__dirname, 'templates', 'login', `${injectionType}.vue.hbs`);
} else {
templatePath = path.join(__dirname, 'templates', 'global', `${injectionType}.vue.hbs`);
Expand Down
4 changes: 3 additions & 1 deletion adminforth/commands/createCustomComponent/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ async function handleFieldComponentCreation(config, resources) {
{ name: '📃 show', value: 'show' },
{ name: '✏️ edit', value: 'edit' },
{ name: '➕ create', value: 'create' },
{ name: '🔍 filter', value: 'filter'},
new Separator(),
{ name: '🔙 BACK', value: '__BACK__' },
]
Expand Down Expand Up @@ -256,6 +257,7 @@ async function handleLoginPageInjectionCreation(config) {
const injectionType = await select({
message: 'Select injection type:',
choices: [
{ name: 'Before Login and password inputs', value: 'beforeLogin' },
{ name: 'After Login and password inputs', value: 'afterLogin' },
{ name: '🔙 BACK', value: '__BACK__' },
],
Expand Down Expand Up @@ -286,7 +288,7 @@ async function handleLoginPageInjectionCreation(config) {
console.log(chalk.dim(`Component generation successful: ${absoluteComponentPath}`));
const configFilePath = path.resolve(process.cwd(), 'index.ts');
console.log(chalk.dim(`Injecting component: ${configFilePath}, ${componentFileName}`));
await injectLoginComponent(configFilePath, `@@/${componentFileName}`);
await injectLoginComponent(configFilePath, `@@/${componentFileName}`, injectionType);

console.log(
chalk.bold.greenBright('You can now open the component in your IDE:'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<input
type="text"
:value="localValue"
@input="onInput"
placeholder="Search"
aria-describedby="helper-text-explanation"
class="inline-flex bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-0 focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 dark:text-white translate-y-0 rounded-l-md rounded-r-md w-full"
/>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';

const emit = defineEmits(['update:modelValue']);

const props = defineProps<{
column: any;
meta?: any;
modelValue: Array<{ operator: string; value: string }> | null;
}>();

const localValue = ref(props.modelValue?.[0]?.value || '');

watch(() => props.modelValue, (val) => {
localValue.value = val?.[0]?.value || '';
});

function onInput(event: Event) {
const target = event.target as HTMLInputElement;
localValue.value = target.value;
emit('update:modelValue', [{ operator: 'ilike', value: target.value }]);
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<div class="text-center text-gray-500 text-sm mt-4">
Login Page Text
</div>
</template>

<script setup>
import { onMounted } from 'vue';

const props = defineProps<{
reason: String
}>();

onMounted(() => {
// Logic on mount if needed
});
</script>

15 changes: 15 additions & 0 deletions adminforth/commands/postinstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import fs from 'fs';
import path from 'path';

import { execSync } from 'child_process';
const spaPath = path.join(import.meta.dirname, 'dist', 'spa');


if (fs.existsSync(spaPath)){
console.log('Installing SPA dependencies...');
execSync('npm ci', { cwd: spaPath, stdio: 'inherit' });
console.log('Installed spa dependencies');
} else {
console.log('SPA dependencies not found');
console.log('current directory', import.meta.dirname);
}
2 changes: 1 addition & 1 deletion adminforth/documentation/blog/2024-10-01-ai-blog/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ model ContentImage {
Create a migration:

```bash
npm run makemigration -- --name add-posts
npm run makemigration -- --name add-posts && npm run migrate:local
```


Expand Down
4 changes: 2 additions & 2 deletions adminforth/documentation/docs/tutorial/001-gettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ This will create a migration file in `migrations` and apply it to the database.
In future, when you need to add new resources, you need to modify `schema.prisma` (add models, change fields, etc.). After doing any modification you need to create a new migration using next command:

```bash
npm run makemigration -- --name <name_of_changes>
npm run makemigration -- --name init && npm run migrate:local
```

Other developers need to pull migration and run `npm run migrateLocal` to apply any unapplied migrations.
Expand Down Expand Up @@ -173,7 +173,7 @@ model apartments {
Run the following command to create a new migration:

```bash
npm run makemigration -- --name add-apartments
npm run makemigration -- --name add-apartments && npm run migrate:local
```

### Step3. Create the `apartments` resource
Expand Down
2 changes: 1 addition & 1 deletion adminforth/documentation/docs/tutorial/01-helloWorld.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ model Post {
Create database using `prisma migrate`:

```bash
npm run makemigration --name init
npm run makemigration --name init && npm run migrate:local
```

## Setting up AdminForth
Expand Down
Loading