Reorganize app workspaces and align Admin architecture
This commit is contained in:
+4
-4
@@ -26,7 +26,7 @@ yarn-error.log
|
|||||||
# Platform specific
|
# Platform specific
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
/backend/public/
|
/apps/backend/public/
|
||||||
/backend/storage/
|
/apps/backend/storage/
|
||||||
/backend/.adonisjs/
|
/apps/backend/.adonisjs/
|
||||||
/backend/database/schema.ts
|
/apps/backend/database/schema.ts
|
||||||
|
|||||||
+3
-3
@@ -3,8 +3,8 @@
|
|||||||
**/build/**
|
**/build/**
|
||||||
**/dist/**
|
**/dist/**
|
||||||
**/coverage/**
|
**/coverage/**
|
||||||
backend/public/**
|
apps/backend/public/**
|
||||||
backend/storage/**
|
apps/backend/storage/**
|
||||||
|
|
||||||
# Handlebars generator templates contain application syntax that is not valid HTML.
|
# Handlebars generator templates contain application syntax that is not valid HTML.
|
||||||
backend/app/templates/**
|
apps/backend/app/templates/**
|
||||||
|
|||||||
@@ -11,8 +11,18 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Moved AdonisJS ESLint and Prettier configuration packages and Japa test dependencies from the
|
||||||
|
root package manifest to the backend workspace so workspace-specific dependencies are owned by
|
||||||
|
`apps/backend`.
|
||||||
|
- Updated the Admin frontend architecture so global providers belong to the `app` composition
|
||||||
|
layer under `app/providers` instead of being modeled as a separate architectural layer.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed Admin and Backend Docker startup on ARM64 by removing manually pinned platform-specific
|
||||||
|
optional dependencies and allowing npm to resolve the correct native packages for the container
|
||||||
|
architecture.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
## [1.1.0] - 2026-07-17
|
## [1.1.0] - 2026-07-17
|
||||||
|
|||||||
@@ -2,15 +2,13 @@ FROM node:24-alpine3.22
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install workspace deps
|
# Copy all workspaces before installation so npm resolves workspace dependencies.
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
|
COPY apps ./apps
|
||||||
|
COPY packages ./packages
|
||||||
|
|
||||||
RUN npm ci --force
|
RUN npm ci --force
|
||||||
|
|
||||||
# Copy project
|
|
||||||
COPY apps/admin ./apps/admin
|
|
||||||
COPY packages ./packages
|
|
||||||
|
|
||||||
WORKDIR /app/apps/admin
|
WORKDIR /app/apps/admin
|
||||||
|
|
||||||
ENV CHOKIDAR_USEPOLLING=true
|
ENV CHOKIDAR_USEPOLLING=true
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { SidebarHeader } from './SidebarHeader';
|
import { SidebarHeader } from './SidebarHeader';
|
||||||
import { SidebarMenu } from './SidebarMenu';
|
import { SidebarMenu } from './SidebarMenu';
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { ChevronFirst } from 'lucide-react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { toAbsoluteUrl } from '#shared/lib/helpers';
|
import { toAbsoluteUrl } from '#shared/lib/helpers';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
|
|
||||||
export function SidebarHeader() {
|
export function SidebarHeader() {
|
||||||
const { settings, storeOption } = useSettings();
|
const { settings, storeOption } = useSettings();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useEffect } from 'react';
|
|||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
import { useIsMobile } from '@crux-kit/hooks';
|
import { useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Sidebar } from './components/Sidebar';
|
import { Sidebar } from './components/Sidebar';
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { useEffect, useState } from 'react'; // Add useState to the imports
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Outlet, useLocation } from 'react-router-dom';
|
import { Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass } from '@crux-kit/hooks';
|
import { useBodyClass } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { useEffect } from 'react';
|
|||||||
import { Link, Outlet, useLocation } from 'react-router-dom';
|
import { Link, Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { useEffect } from 'react';
|
|||||||
import { Link, Outlet } from 'react-router-dom';
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
||||||
// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet';
|
// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Outlet, useLocation } from 'react-router';
|
import { Outlet, useLocation } from 'react-router';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import React from 'react';
|
|||||||
import { Outlet, useLocation } from 'react-router-dom';
|
import { Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Sidebar } from './components/Sidebar';
|
import { Sidebar } from './components/Sidebar';
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Link, Outlet, useLocation } from 'react-router-dom';
|
import { Link, Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass } from '@crux-kit/hooks';
|
import { useBodyClass } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar';
|
import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar';
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { useEffect } from 'react';
|
|||||||
import { Link, Outlet } from 'react-router-dom';
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
||||||
// import { ChatSheet } from '#shared/partials/topbar/chat-sheet';
|
// import { ChatSheet } from '#shared/partials/topbar/chat-sheet';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderSearch } from './HeaderSearch';
|
import { HeaderSearch } from './HeaderSearch';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Link, Outlet, useLocation } from 'react-router';
|
import { Link, Outlet, useLocation } from 'react-router';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Link, Outlet } from 'react-router-dom';
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Sidebar } from './components/Sidebar';
|
import { Sidebar } from './components/Sidebar';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { queryClient } from '#providers/QueryProvider';
|
import { queryClient } from '#app/providers/QueryProvider';
|
||||||
import { adminDetailedKeyBuilder, adminListKeyBuilder, permissionListKeyBuilder, roleDetailedKeyBuilder, roleListKeyBuilder } from './keys';
|
import { adminDetailedKeyBuilder, adminListKeyBuilder, permissionListKeyBuilder, roleDetailedKeyBuilder, roleListKeyBuilder } from './keys';
|
||||||
|
|
||||||
export const invalidateAdminList = async () => {
|
export const invalidateAdminList = async () => {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { PropsWithChildren, useState } from 'react';
|
import { PropsWithChildren, useState } from 'react';
|
||||||
|
import { queryClient } from '#app/providers/QueryProvider';
|
||||||
import { AuthApi } from '#core/Auth/data/api/api';
|
import { AuthApi } from '#core/Auth/data/api/api';
|
||||||
import { UpdateUserPayload } from '#core/Auth/data/api/dto';
|
import { UpdateUserPayload } from '#core/Auth/data/api/dto';
|
||||||
import UserMapper from '#core/Auth/data/mappers/UserMapper';
|
import UserMapper from '#core/Auth/data/mappers/UserMapper';
|
||||||
import * as authHelper from '#core/Auth/data/stores/localStorage';
|
import * as authHelper from '#core/Auth/data/stores/localStorage';
|
||||||
import { AuthModel, AuthUser } from '#core/Auth/entities';
|
import { AuthModel, AuthUser } from '#core/Auth/entities';
|
||||||
import { queryClient } from '#providers/QueryProvider';
|
|
||||||
import { AuthContext } from './context';
|
import { AuthContext } from './context';
|
||||||
|
|
||||||
export function AuthProvider({ children }: PropsWithChildren) {
|
export function AuthProvider({ children }: PropsWithChildren) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { InfiniteData, QueryKey } from '@tanstack/react-query';
|
import { InfiniteData, QueryKey } from '@tanstack/react-query';
|
||||||
|
import { queryClient } from '#app/providers/QueryProvider';
|
||||||
import { EntryDTO } from '#core/FileManager/data/api/dto';
|
import { EntryDTO } from '#core/FileManager/data/api/dto';
|
||||||
import { AUDIO_EXTENSIONS, getFileExtension, IMAGE_EXTENSIONS, PDF_EXTENSIONS, PLAINTEXT_EXTENSIONS, VIDEO_EXTENSIONS } from '#core/FileManager/shared/file/extension';
|
import { AUDIO_EXTENSIONS, getFileExtension, IMAGE_EXTENSIONS, PDF_EXTENSIONS, PLAINTEXT_EXTENSIONS, VIDEO_EXTENSIONS } from '#core/FileManager/shared/file/extension';
|
||||||
import { ensureLeadingSlash } from '#core/FileManager/shared/path/leadingSlash';
|
import { ensureLeadingSlash } from '#core/FileManager/shared/path/leadingSlash';
|
||||||
import { queryClient } from '#providers/QueryProvider';
|
|
||||||
import { fetchEntries } from './entries';
|
import { fetchEntries } from './entries';
|
||||||
import { entriesKeyBuilder, EntriesQueryPayload } from './keys';
|
import { entriesKeyBuilder, EntriesQueryPayload } from './keys';
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export default function TutorialSection() {
|
|||||||
Compare frontend permission constants in{' '}
|
Compare frontend permission constants in{' '}
|
||||||
<code>apps/admin/src/modules/<name>/config/meta.ts</code> with backend
|
<code>apps/admin/src/modules/<name>/config/meta.ts</code> with backend
|
||||||
permissions in{' '}
|
permissions in{' '}
|
||||||
<code>backend/modules/<ModuleName>/config/permissions.ts</code>.
|
<code>apps/backend/modules/<ModuleName>/config/permissions.ts</code>.
|
||||||
</li>
|
</li>
|
||||||
<li>Confirm the current admin role owns the generated view permission.</li>
|
<li>Confirm the current admin role owns the generated view permission.</li>
|
||||||
<li>Check that the module manifest exposes its menu and routes.</li>
|
<li>Check that the module manifest exposes its menu and routes.</li>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
import { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||||
|
import { queryClient } from '#app/providers/QueryProvider';
|
||||||
import { getAuth, removeAuth } from '#core/Auth/data/stores/localStorage';
|
import { getAuth, removeAuth } from '#core/Auth/data/stores/localStorage';
|
||||||
import { queryClient } from '#providers/QueryProvider';
|
|
||||||
|
|
||||||
export function requestInterceptorSuccess(
|
export function requestInterceptorSuccess(
|
||||||
config: InternalAxiosRequestConfig
|
config: InternalAxiosRequestConfig
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { StrictMode } from 'react';
|
import { StrictMode } from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import AppProviders from '#app/providers/AppProviders';
|
||||||
import AppRouting from '#app/routing/AppRouting';
|
import AppRouting from '#app/routing/AppRouting';
|
||||||
import AppProviders from '#providers/AppProviders';
|
|
||||||
import './app/css/styles.css';
|
import './app/css/styles.css';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { queryClient } from '#app/providers/QueryProvider';
|
||||||
import { axiosClient } from '#infrastructure/axios';
|
import { axiosClient } from '#infrastructure/axios';
|
||||||
import { queryClient } from '#providers/QueryProvider';
|
|
||||||
import { MODULE_API_ENDPOINT } from '../config/meta';
|
import { MODULE_API_ENDPOINT } from '../config/meta';
|
||||||
import { Entity } from '../entities/Entity';
|
import { Entity } from '../entities/Entity';
|
||||||
import { detailedKeyBuilder } from './keys';
|
import { detailedKeyBuilder } from './keys';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { keepPreviousData, useQuery } from '@tanstack/react-query';
|
import { keepPreviousData, useQuery } from '@tanstack/react-query';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { queryClient } from '#app/providers/QueryProvider';
|
||||||
import { axiosClient } from '#infrastructure/axios';
|
import { axiosClient } from '#infrastructure/axios';
|
||||||
import { getPaginationInfo, ListQueryParams, SuccessListResponse } from '#infrastructure/reactQuery';
|
import { getPaginationInfo, ListQueryParams, SuccessListResponse } from '#infrastructure/reactQuery';
|
||||||
import { queryClient } from '#providers/QueryProvider';
|
|
||||||
import { MODULE_API_ENDPOINT } from '../config/meta';
|
import { MODULE_API_ENDPOINT } from '../config/meta';
|
||||||
import { Entity } from '../entities/Entity';
|
import { Entity } from '../entities/Entity';
|
||||||
import { listKeyBuilder } from './keys';
|
import { listKeyBuilder } from './keys';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Editor as TinyMCEEditorReact } from '@tinymce/tinymce-react';
|
|||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { Editor } from 'tinymce';
|
import { Editor } from 'tinymce';
|
||||||
import { useLanguage } from '#providers/I18nProvider';
|
import { useLanguage } from '#app/providers/I18nProvider';
|
||||||
import { Statusbar } from './components/Statusbar';
|
import { Statusbar } from './components/Statusbar';
|
||||||
import { Toolbar } from './components/Toolbar';
|
import { Toolbar } from './components/Toolbar';
|
||||||
import { apiKey, createConfig, defaultToolbarLayout, ToolbarLayout, ToolbarOptions } from './config';
|
import { apiKey, createConfig, defaultToolbarLayout, ToolbarLayout, ToolbarOptions } from './config';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useFormContext } from 'react-hook-form';
|
import { useFormContext } from 'react-hook-form';
|
||||||
import { InputTimeFormat } from '@crux-kit/types';
|
import { InputTimeFormat } from '@crux-kit/types';
|
||||||
|
import { useLanguage } from '#app/providers/I18nProvider';
|
||||||
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '#shared/ui/form';
|
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '#shared/ui/form';
|
||||||
import { TimeInput } from '#shared/ui/TimeInput';
|
import { TimeInput } from '#shared/ui/TimeInput';
|
||||||
import { useLanguage } from '#providers/I18nProvider';
|
|
||||||
|
|
||||||
export const InputTime: React.FC<{
|
export const InputTime: React.FC<{
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ReactNode } from 'react';
|
|||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { Language } from '#app/i18n/types';
|
import { Language } from '#app/i18n/types';
|
||||||
|
import { useLanguage } from '#app/providers/I18nProvider';
|
||||||
import { IntlName } from '#infrastructure/IntlName';
|
import { IntlName } from '#infrastructure/IntlName';
|
||||||
import { useAuth } from '#core/Auth/providers/AuthProvider';
|
import { useAuth } from '#core/Auth/providers/AuthProvider';
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '#shared/ui/Avatar';
|
import { Avatar, AvatarFallback, AvatarImage } from '#shared/ui/Avatar';
|
||||||
@@ -11,7 +12,6 @@ import { Badge } from '#shared/ui/Badge';
|
|||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '#shared/ui/DropdownMenu';
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '#shared/ui/DropdownMenu';
|
||||||
import { Switch } from '#shared/ui/Switch';
|
import { Switch } from '#shared/ui/Switch';
|
||||||
import { useLanguage } from '#providers/I18nProvider';
|
|
||||||
|
|
||||||
export function UserDropdownMenu({ trigger }: { trigger: ReactNode }) {
|
export function UserDropdownMenu({ trigger }: { trigger: ReactNode }) {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { cva, type VariantProps } from 'class-variance-authority';
|
import { cva, type VariantProps } from 'class-variance-authority';
|
||||||
import { type ReactNode } from 'react';
|
import { type ReactNode } from 'react';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
|
|
||||||
const containerVariants = cva('w-full mx-auto px-4 lg:px-6', {
|
const containerVariants = cva('w-full mx-auto px-4 lg:px-6', {
|
||||||
variants: {
|
variants: {
|
||||||
|
|||||||
@@ -3,17 +3,15 @@ FROM node:24-alpine3.22
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy only root workspace files first
|
# Copy all workspaces before installation so npm can resolve their dependencies.
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
|
COPY apps ./apps
|
||||||
# Install workspace dependencies (monorepo-aware)
|
|
||||||
RUN npm ci --force
|
|
||||||
|
|
||||||
# Copy backend source
|
|
||||||
COPY backend ./backend
|
|
||||||
COPY packages ./packages
|
COPY packages ./packages
|
||||||
|
|
||||||
WORKDIR /app/backend
|
# Install workspace dependencies (monorepo-aware).
|
||||||
|
RUN npm ci --force
|
||||||
|
|
||||||
|
WORKDIR /app/apps/backend
|
||||||
|
|
||||||
# Expose dev port
|
# Expose dev port
|
||||||
EXPOSE 3333
|
EXPOSE 3333
|
||||||
+3
-2
@@ -136,8 +136,9 @@ export default class MakeModuleController {
|
|||||||
const modulePath = join(appBase, 'modules', moduleName)
|
const modulePath = join(appBase, 'modules', moduleName)
|
||||||
|
|
||||||
const snake = this.snakeCase(table)
|
const snake = this.snakeCase(table)
|
||||||
const clientBase = join(appBase, '..', 'apps', 'admin', 'src', 'modules', moduleName)
|
// Backend and admin are sibling workspaces under apps/.
|
||||||
const templateModuleDir = join(appBase, '..', 'apps', 'admin', 'src', 'modules', '_template')
|
const clientBase = join(appBase, '..', 'admin', 'src', 'modules', moduleName)
|
||||||
|
const templateModuleDir = join(appBase, '..', 'admin', 'src', 'modules', '_template')
|
||||||
|
|
||||||
const paths = {
|
const paths = {
|
||||||
// backend
|
// backend
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user