├── LICENSE.md ├── README.md ├── artisan ├── composer.json ├── config ├── resource │ └── listeners.php └── superv.php ├── database ├── factories │ └── ModelFactory.php └── migrations │ ├── 2018_02_00_000000_create_addons_table.php │ ├── 2018_02_15_184614_create_profiles_table.php │ ├── 2018_04_19_035358_create_media_table.php │ ├── 2018_10_25_145003_create_authorization_tables.php │ ├── 2018_10_25_233352_create_users_resource.php │ ├── 2019_07_22_213036_create_tasks_table.php │ └── 2019_08_08_000000_create_drops_table.php ├── resources ├── lang │ ├── en.json │ └── tr.json ├── skeletons │ └── panel │ │ ├── frontend │ │ ├── .eslintrc.js.stub │ │ ├── .gitignore │ │ ├── babel.config.js.stub │ │ ├── package.json.stub │ │ ├── postcss.config.js.stub │ │ ├── public │ │ │ ├── img │ │ │ │ ├── favicon.png │ │ │ │ ├── logo.png │ │ │ │ └── logo.svg │ │ │ └── index.html.stub │ │ ├── src │ │ │ ├── Panel.vue.stub │ │ │ ├── app │ │ │ │ ├── pages │ │ │ │ │ └── Login.vue.stub │ │ │ │ └── routes.js.stub │ │ │ └── main.js.stub │ │ ├── tailwind.config.js.stub │ │ └── vue.config.js.stub │ │ ├── routes │ │ └── global.php.stub │ │ ├── src │ │ ├── Panel.php.stub │ │ ├── PanelController.php.stub │ │ └── PanelServiceProvider.php.stub │ │ └── tools │ │ └── index.js.stub └── stubs │ ├── addons │ ├── addon.stub │ ├── agent.stub │ ├── composer.stub │ ├── drop.stub │ ├── module.stub │ ├── panel.stub │ ├── provider.stub │ ├── testing │ │ ├── AddonTest.stub │ │ └── TestCase.stub │ ├── theme.stub │ └── tool.stub │ ├── blank.stub │ ├── create.stub │ ├── generator │ └── migration.stub │ └── update.stub ├── routes └── all-ports │ ├── all-ports.php │ ├── entry-routes.php │ ├── form-routes.php │ ├── relation-routes.php │ └── resource-routes.php ├── src ├── Adapters │ ├── AdapterServiceProvider.php │ ├── LaravelDispatcher.php │ ├── LaravelFileSystem.php │ └── LaravelValidator.php ├── Console │ ├── InstallSuperVCommand.php │ ├── Jobs │ │ ├── EnvFile.php │ │ └── InstallSuperV.php │ └── SuperVUninstallCommand.php ├── Contracts │ ├── Arrayable.php │ ├── Command.php │ ├── Container.php │ ├── Dispatcher.php │ ├── Filesystem.php │ ├── Hibernatable.php │ ├── ServiceProvider.php │ └── Validator.php ├── Domains │ ├── Addon │ │ ├── Addon.php │ │ ├── AddonCollection.php │ │ ├── AddonModel.php │ │ ├── AddonServiceProvider.php │ │ ├── Console │ │ │ ├── AddonInstallCommand.php │ │ │ ├── AddonMakeMigrationCommand.php │ │ │ ├── AddonReinstallCommand.php │ │ │ ├── AddonRunMigrationCommand.php │ │ │ ├── AddonUninstallCommand.php │ │ │ ├── MakeAddonCommand.php │ │ │ ├── MakeModuleCommand.php │ │ │ └── MakePanelCommand.php │ │ ├── Contracts │ │ │ └── AddonLocator.php │ │ ├── Events │ │ │ ├── AddonBootedEvent.php │ │ │ ├── AddonInstalledEvent.php │ │ │ ├── AddonUninstallingEvent.php │ │ │ └── MakingAddonEvent.php │ │ ├── Features │ │ │ ├── MakeAddon.php │ │ │ └── MakeAddonRequest.php │ │ ├── Installer.php │ │ ├── Jobs │ │ │ ├── CreateAddonFiles.php │ │ │ ├── CreateAddonPaths.php │ │ │ ├── EnableConfigFiles.php │ │ │ ├── MakeAddonModel.php │ │ │ ├── SeedAddon.php │ │ │ └── UninstallAddonJob.php │ │ ├── Listeners │ │ │ ├── AddonBootedListener.php │ │ │ └── AddonInstalledListener.php │ │ ├── Locator.php │ │ ├── Skeleton.php │ │ └── Types │ │ │ ├── Droplet.php │ │ │ ├── Module.php │ │ │ ├── Panel │ │ │ ├── Panel.php │ │ │ └── PanelServiceProvider.php │ │ │ └── Tool.php │ ├── Auth │ │ ├── Access │ │ │ ├── Access.php │ │ │ ├── Action.php │ │ │ ├── AuthorizationFailedException.php │ │ │ ├── Guard │ │ │ │ ├── Guard.php │ │ │ │ ├── Guardable.php │ │ │ │ └── HasGuardableItems.php │ │ │ ├── HasActions.php │ │ │ ├── HasActionsInterface.php │ │ │ └── Role.php │ │ ├── Account.php │ │ ├── AuthServiceProvider.php │ │ ├── Concerns │ │ │ ├── AuthenticatesUsers.php │ │ │ ├── HasUser.php │ │ │ └── RegistersUsers.php │ │ ├── Console │ │ │ ├── AssignRoleCommand.php │ │ │ └── SuperVUserCommand.php │ │ ├── Contracts │ │ │ ├── Account.php │ │ │ ├── User.php │ │ │ └── Users.php │ │ ├── Events │ │ │ └── UserCreatedEvent.php │ │ ├── JWTGuard.php │ │ ├── PlatformUserProvider.php │ │ ├── Profile.php │ │ ├── User.php │ │ ├── UserRegistrar.php │ │ └── Users.php │ ├── Database │ │ ├── Events │ │ │ ├── ColumnCreatedEvent.php │ │ │ ├── ColumnDroppedEvent.php │ │ │ ├── ColumnUpdatedEvent.php │ │ │ ├── TableCreatedEvent.php │ │ │ ├── TableCreatingEvent.php │ │ │ ├── TableDroppedEvent.php │ │ │ ├── TableDroppingEvent.php │ │ │ ├── TableInsertEvent.php │ │ │ └── TableUpdateEvent.php │ │ ├── Jobs │ │ │ └── BuildBlueprintJob.php │ │ ├── Migrations │ │ │ ├── Console │ │ │ │ ├── MigrateCommand.php │ │ │ │ ├── MigrateMakeCommand.php │ │ │ │ ├── RefreshCommand.php │ │ │ │ ├── ResetCommand.php │ │ │ │ └── RollbackCommand.php │ │ │ ├── DatabaseMigrationRepository.php │ │ │ ├── Migration.php │ │ │ ├── MigrationCreator.php │ │ │ ├── MigrationServiceProvider.php │ │ │ ├── Migrator.php │ │ │ ├── PlatformMigration.php │ │ │ └── Scopes.php │ │ ├── Model │ │ │ ├── Contracts │ │ │ │ └── EntryContract.php │ │ │ ├── Entry.php │ │ │ ├── Listener.php │ │ │ ├── MakesEntry.php │ │ │ └── Repository.php │ │ └── Schema │ │ │ ├── Blueprint.php │ │ │ ├── Builder.php │ │ │ ├── ColumnDefinition.php │ │ │ ├── CreatesFields.php │ │ │ ├── CreatesRelations.php │ │ │ ├── Schema.php │ │ │ └── SchemaService.php │ ├── Drop │ │ ├── BaseRepoHandler.php │ │ ├── Contracts │ │ │ ├── Drop.php │ │ │ └── RepoHandler.php │ │ ├── DropModel.php │ │ ├── DropRepoModel.php │ │ ├── Drops.php │ │ └── Factory.php │ ├── Mail │ │ ├── MailSender.php │ │ ├── MailTemplate.php │ │ └── TemplateSender.php │ ├── Media │ │ ├── HasMedia.php │ │ ├── Media.php │ │ ├── MediaBag.php │ │ ├── MediaOptions.php │ │ └── MediaOwner.php │ ├── Port │ │ ├── ApiPort.php │ │ ├── Factory.php │ │ ├── Hub.php │ │ ├── Port.php │ │ ├── PortDetectedEvent.php │ │ └── PortDetector.php │ ├── Resource │ │ ├── Action │ │ │ ├── Action.php │ │ │ ├── Contracts │ │ │ │ └── ActionContract.php │ │ │ ├── CreateEntryAction.php │ │ │ ├── DeleteEntryAction.php │ │ │ ├── DetachEntryAction.php │ │ │ ├── EditEntryAction.php │ │ │ ├── ModalAction.php │ │ │ ├── RequestAction.php │ │ │ ├── ResourceEntryAction.php │ │ │ ├── RestoreEntryAction.php │ │ │ └── ViewEntryAction.php │ │ ├── ColumnFieldMapper.php │ │ ├── Command │ │ │ └── ResourceImportCommand.php │ │ ├── Contracts │ │ │ ├── AcceptsEntry.php │ │ │ ├── AcceptsParentEntry.php │ │ │ ├── Filter │ │ │ │ ├── Filter.php │ │ │ │ └── ProvidesField.php │ │ │ ├── HandlesRequests.php │ │ │ ├── InlinesForm.php │ │ │ ├── ProvidesFields.php │ │ │ ├── ProvidesFilter.php │ │ │ ├── ProvidesForm.php │ │ │ ├── ProvidesQuery.php │ │ │ ├── ProvidesTable.php │ │ │ ├── ProvidesUIComponent.php │ │ │ ├── RequiresEntry.php │ │ │ └── RequiresResource.php │ │ ├── Database │ │ │ ├── Entry │ │ │ │ ├── AnonymousModel.php │ │ │ │ ├── Builder.php │ │ │ │ ├── DatabaseEntry.php │ │ │ │ ├── EntryRepository.php │ │ │ │ ├── EntryRepositoryInterface.php │ │ │ │ ├── EntryRouter.php │ │ │ │ ├── Events │ │ │ │ │ ├── EntryCreatedEvent.php │ │ │ │ │ ├── EntryCreatingEvent.php │ │ │ │ │ ├── EntryDeletedEvent.php │ │ │ │ │ ├── EntryRetrievedEvent.php │ │ │ │ │ ├── EntrySavedEvent.php │ │ │ │ │ └── EntrySavingEvent.php │ │ │ │ ├── ResourceEntry.php │ │ │ │ ├── ResourceEntryFake.php │ │ │ │ └── Restorable.php │ │ │ └── ResourceRepository.php │ │ ├── Events │ │ │ ├── ResourceConfigResolvedEvent.php │ │ │ └── ResourceCreatedEvent.php │ │ ├── Extension │ │ │ ├── Contracts │ │ │ │ ├── ExtendsMultipleResources.php │ │ │ │ ├── ExtendsResource.php │ │ │ │ ├── ObservesEntryCreating.php │ │ │ │ ├── ObservesEntryRetrieved.php │ │ │ │ ├── ObservesEntrySaved.php │ │ │ │ └── ObservesEntrySaving.php │ │ │ ├── Extension.php │ │ │ ├── RegisterExtensions.php │ │ │ ├── RegisterExtensionsInPath.php │ │ │ └── RegisterHooksInPath.php │ │ ├── Fake.php │ │ ├── Features │ │ │ └── UserType.php │ │ ├── Field │ │ │ ├── Accessor.php │ │ │ ├── Contracts │ │ │ │ ├── AltersDatabaseTable.php │ │ │ │ ├── FieldInterface.php │ │ │ │ ├── FieldTypeInterface.php │ │ │ │ ├── GhostField.php │ │ │ │ ├── HandlesRpc.php │ │ │ │ ├── HasAccessor.php │ │ │ │ ├── HasModifier.php │ │ │ │ ├── HasPresenter.php │ │ │ │ ├── RequiresDbColumn.php │ │ │ │ ├── ResourceField.php │ │ │ │ └── SortsQuery.php │ │ │ ├── DoesNotInteractWithTable.php │ │ │ ├── Field.php │ │ │ ├── FieldComposer.php │ │ │ ├── FieldConfig.php │ │ │ ├── FieldFactory.php │ │ │ ├── FieldModel.php │ │ │ ├── FieldQuerySorter.php │ │ │ ├── FieldRepository.php │ │ │ ├── FieldRules.php │ │ │ ├── FieldType.php │ │ │ ├── GhostField.php │ │ │ ├── Jobs │ │ │ │ ├── GetRuleMessages.php │ │ │ │ ├── HandleFieldRpc.php │ │ │ │ └── SetFieldValue.php │ │ │ ├── Modifier.php │ │ │ ├── Rules.php │ │ │ ├── Rules │ │ │ │ └── HumanNameRule.php │ │ │ └── Types │ │ │ │ ├── ArrayField.php │ │ │ │ ├── BelongsToField.php │ │ │ │ ├── BelongsToManyField.php │ │ │ │ ├── BooleanField.php │ │ │ │ ├── CheckboxField.php │ │ │ │ ├── DatetimeField.php │ │ │ │ ├── DictionaryField.php │ │ │ │ ├── EmailField.php │ │ │ │ ├── EncryptedField.php │ │ │ │ ├── FileField.php │ │ │ │ ├── ModalFormField.php │ │ │ │ ├── MorphToField.php │ │ │ │ ├── NumberField.php │ │ │ │ ├── Polymorphic │ │ │ │ ├── PolymorphicField.php │ │ │ │ └── PolymorphicFieldConfig.php │ │ │ │ ├── Relation │ │ │ │ ├── RelationField.php │ │ │ │ ├── RelationFieldConfig.php │ │ │ │ └── RelationType.php │ │ │ │ ├── SelectField.php │ │ │ │ ├── SubFormField.php │ │ │ │ ├── TextField.php │ │ │ │ └── TextareaField.php │ │ ├── Filter │ │ │ ├── ApplyFilters.php │ │ │ ├── BooleanFilter.php │ │ │ ├── DecodeRequest.php │ │ │ ├── DistinctFilter.php │ │ │ ├── Filter.php │ │ │ ├── SearchFilter.php │ │ │ └── SelectFilter.php │ │ ├── Form │ │ │ ├── Contracts │ │ │ │ ├── FormBuilderInterface.php │ │ │ │ ├── FormFieldInterface.php │ │ │ │ └── FormInterface.php │ │ │ ├── Features │ │ │ │ └── SubmitForm.php │ │ │ ├── FieldLocation.php │ │ │ ├── Form.php │ │ │ ├── FormBuilder.php │ │ │ ├── FormComposer.php │ │ │ ├── FormData.php │ │ │ ├── FormFactory.php │ │ │ ├── FormField.php │ │ │ ├── FormFields.php │ │ │ ├── FormModel.php │ │ │ ├── FormRepository.php │ │ │ ├── FormResponse.php │ │ │ └── Jobs │ │ │ │ └── ValidateForm.php │ │ ├── Generator │ │ │ ├── FieldGenerator.php │ │ │ ├── IndexGenerator.php │ │ │ ├── RelationGenerator.php │ │ │ ├── ResourceGenerator.php │ │ │ └── Schema.php │ │ ├── Hook │ │ │ ├── Actions │ │ │ │ └── RegisterAddonHooks.php │ │ │ ├── Contracts │ │ │ │ ├── AfterCreatedHook.php │ │ │ │ ├── AfterDeletedHook.php │ │ │ │ ├── AfterRetrievedHook.php │ │ │ │ ├── AfterSavedHook.php │ │ │ │ ├── BeforeCreatingHook.php │ │ │ │ ├── BeforeSavingHook.php │ │ │ │ ├── ConfigResolvedHook.php │ │ │ │ ├── FormResolvedHook.php │ │ │ │ ├── FormResolvingHook.php │ │ │ │ ├── FormValidatingHook.php │ │ │ │ ├── HookByRole.php │ │ │ │ ├── HookHandlerInterface.php │ │ │ │ ├── ListDataHook.php │ │ │ │ ├── ListQueryResolvedHook.php │ │ │ │ ├── ListResolvedHook.php │ │ │ │ ├── PageRenderedHook.php │ │ │ │ ├── PageResolvedHook.php │ │ │ │ ├── QueryResolvedHook.php │ │ │ │ ├── ResourceResolvedHook.php │ │ │ │ └── ScopeHook.php │ │ │ ├── FieldsHookHandler.php │ │ │ ├── FormsHookHandler.php │ │ │ ├── HookHandler.php │ │ │ ├── HookManager.php │ │ │ ├── ListsHookHandler.php │ │ │ ├── ObserverHookHandler.php │ │ │ ├── PagesHookHandler.php │ │ │ ├── ResourceHookHandler.php │ │ │ └── ScopesHookHandler.php │ │ ├── Http │ │ │ ├── Controllers │ │ │ │ ├── Dashboard │ │ │ │ │ ├── ResourceDashboardController.php │ │ │ │ │ └── ResourceEntryDashboardController.php │ │ │ │ ├── FormController.php │ │ │ │ ├── ListController.php │ │ │ │ ├── PublicFormController.php │ │ │ │ ├── Relation │ │ │ │ │ ├── LookupController.php │ │ │ │ │ ├── RelationController.php │ │ │ │ │ ├── RelationFormController.php │ │ │ │ │ └── RelationIndexController.php │ │ │ │ ├── ResourceController.php │ │ │ │ └── ResourceViewController.php │ │ │ ├── Middleware │ │ │ │ └── WatchActivity.php │ │ │ └── ResolvesResource.php │ │ ├── Jobs │ │ │ ├── AccessEntryAttributes.php │ │ │ ├── CreateNavigation.php │ │ │ ├── CreatePivotTable.php │ │ │ ├── CreatePivotTableV2.php │ │ │ ├── CreatePlatformResourceForms.php │ │ │ ├── DeleteAddonResources.php │ │ │ ├── DeleteResource.php │ │ │ ├── GetTableResource.php │ │ │ ├── MakeLookupOptions.php │ │ │ └── ModifyEntryAttributes.php │ │ ├── Listeners │ │ │ ├── CreateResource.php │ │ │ ├── CreateResourceAuthActions.php │ │ │ ├── CreateResourceForm.php │ │ │ ├── DeleteField.php │ │ │ ├── RecordActivity.php │ │ │ ├── RegisterEntryEventListeners.php │ │ │ ├── RegisterExtensions.php │ │ │ ├── SaveCreatedBy.php │ │ │ ├── SaveFieldEntry.php │ │ │ └── SaveUpdatedBy.php │ │ ├── Nav │ │ │ ├── Nav.php │ │ │ ├── NavGuard.php │ │ │ └── Section.php │ │ ├── Relation │ │ │ ├── Actions │ │ │ │ ├── AttachEntriesAction.php │ │ │ │ └── LookupAttachablesAction.php │ │ │ ├── Contracts │ │ │ │ └── ProvidesField.php │ │ │ ├── Relation.php │ │ │ ├── RelationCollection.php │ │ │ ├── RelationConfig.php │ │ │ ├── RelationFactory.php │ │ │ ├── RelationModel.php │ │ │ ├── RelationRepository.php │ │ │ ├── RelationType.php │ │ │ └── Types │ │ │ │ ├── BelongsTo.php │ │ │ │ ├── BelongsToMany.php │ │ │ │ ├── HasMany.php │ │ │ │ ├── HasOne.php │ │ │ │ ├── MorphMany.php │ │ │ │ ├── MorphOne.php │ │ │ │ ├── MorphTo.php │ │ │ │ └── MorphToMany.php │ │ ├── Repository.php │ │ ├── Resource.php │ │ ├── Resource │ │ │ ├── Extender.php │ │ │ ├── Fields.php │ │ │ ├── IndexFields.php │ │ │ ├── LabelConcern.php │ │ │ ├── RepoConcern.php │ │ │ ├── ResourceActivityEvent.php │ │ │ ├── ResourceView.php │ │ │ └── TestHelper.php │ │ ├── ResourceConfig.php │ │ ├── ResourceDriver.php │ │ ├── ResourceFactory.php │ │ ├── ResourceModel.php │ │ ├── ResourceServiceProvider.php │ │ ├── Router.php │ │ ├── Support │ │ │ └── PlatformBlueprints.php │ │ ├── Table │ │ │ ├── Actions │ │ │ │ └── SelectionAction.php │ │ │ ├── Contracts │ │ │ │ ├── AltersTableQuery.php │ │ │ │ ├── TableDataProviderInterface.php │ │ │ │ └── TableInterface.php │ │ │ ├── EloquentTableDataProvider.php │ │ │ ├── FormTable.php │ │ │ ├── ResourceTable.php │ │ │ ├── Table.php │ │ │ └── TableComposer.php │ │ ├── Testing │ │ │ ├── FormTester.php │ │ │ ├── ResourceFormTester.php │ │ │ └── ResourceTestHelpers.php │ │ ├── UI │ │ │ └── ResourceDashboard.php │ │ └── Visibility │ │ │ ├── Condition.php │ │ │ └── Visibility.php │ ├── Routing │ │ ├── Action.php │ │ ├── RouteRegistrar.php │ │ ├── Router.php │ │ └── UrlGenerator.php │ ├── TaskManager │ │ ├── Contracts │ │ │ ├── Task.php │ │ │ └── TaskHandler.php │ │ ├── DeployTaskJob.php │ │ ├── Deployer.php │ │ ├── TaskBuilder.php │ │ ├── TaskModel.php │ │ └── TaskStatus.php │ └── UI │ │ ├── Components │ │ ├── ActionComponent.php │ │ ├── BaseComponent.php │ │ ├── Button.php │ │ ├── Component.php │ │ ├── ComponentContract.php │ │ ├── Concerns │ │ │ └── StyleHelper.php │ │ ├── FormComponent.php │ │ ├── Html.php │ │ ├── ImageComponent.php │ │ ├── Layout │ │ │ └── RowComponent.php │ │ ├── PageComponent.php │ │ ├── Props.php │ │ └── TableComponent.php │ │ ├── Http │ │ └── Controllers │ │ │ └── WakeupController.php │ │ ├── Jobs │ │ └── MakeComponentTree.php │ │ ├── Nucleo │ │ ├── BarChart.php │ │ ├── Chart.php │ │ ├── ChartData.php │ │ ├── PieChart.php │ │ ├── SvBlock.php │ │ ├── SvCard.php │ │ ├── SvColumn.php │ │ ├── SvComponent.php │ │ ├── SvTab.php │ │ └── SvTabs.php │ │ └── Page │ │ ├── EntryPage.php │ │ ├── MakeTablePage.php │ │ ├── Page.php │ │ └── ResourcePage.php ├── Events │ ├── BaseEvent.php │ ├── PlatformBootedEvent.php │ ├── PlatformBootingEvent.php │ └── PlatformInstalledEvent.php ├── Exceptions │ ├── AddonNotFoundException.php │ ├── PathNotFoundException.php │ ├── PlatformException.php │ ├── PlatformExceptionHandler.php │ └── ValidationException.php ├── Facades │ ├── CurrentFacade.php │ ├── HubFacade.php │ └── PlatformFacade.php ├── Http │ ├── Controllers │ │ ├── AuthController.php │ │ ├── BaseApiController.php │ │ ├── BaseController.php │ │ └── DataController.php │ └── Middleware │ │ ├── AutoLoginDev.php │ │ ├── PlatformAuthenticate.php │ │ └── SetLocale.php ├── Listeners │ ├── PortDetectedListener.php │ └── RouteMatchedListener.php ├── Platform.php ├── PlatformServiceProvider.php ├── Providers │ └── BaseServiceProvider.php ├── Resources │ ├── Auth │ │ ├── ActionsList.php │ │ └── DeleteActionsAction.php │ ├── FieldsList.php │ ├── FormsList.php │ ├── FormsResource.php │ ├── MediaList.php │ ├── ResourceActivityDashboardPage.php │ ├── ResourcesList.php │ ├── TasksList.php │ └── Users │ │ ├── ImpersonateAction.php │ │ ├── UpdatePasswordAction.php │ │ ├── UsersEntryDashboardPage.php │ │ ├── UsersForm.php │ │ ├── UsersList.php │ │ └── UsersResource.php ├── Support │ ├── Composer │ │ ├── Composable.php │ │ ├── Composer.php │ │ ├── EntryComposer.php │ │ ├── Payload.php │ │ └── Tokens.php │ ├── Concerns │ │ ├── FiresCallbacks.php │ │ ├── HasConfig.php │ │ ├── HasOptions.php │ │ ├── HasPath.php │ │ └── Hydratable.php │ ├── Current.php │ ├── Dispatchable.php │ ├── Fireable.php │ ├── Identifier.php │ ├── IdentifierType.php │ ├── Inflator.php │ ├── JsonFile.php │ ├── Parser.php │ ├── Path.php │ ├── RelativePath.php │ ├── ValueObject.php │ └── helpers.php └── Testing │ ├── FormComponent.php │ ├── HelperComponent.php │ ├── ListComponent.php │ ├── PlatformTestCase.php │ └── TestHelpers.php └── storage └── framework └── .gitignore /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Muhammed Ali Selcuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /database/factories/ModelFactory.php: -------------------------------------------------------------------------------- 1 | define(SuperV\Platform\Domains\Auth\User::class, function (Faker\Generator $faker) { 17 | static $password; 18 | 19 | return [ 20 | 'email' => $faker->unique()->safeEmail, 21 | 'password' => $password ?: $password = '$2y$10$lEElUpT9ssdSw4XVVEUt5OaJnBzgcmcE6MJ2Rrov4dKPEjuRD6dd.', // secret, 22 | 'remember_token' => str_random(10), 23 | ]; 24 | }); 25 | 26 | -------------------------------------------------------------------------------- /database/migrations/2018_02_15_184614_create_profiles_table.php: -------------------------------------------------------------------------------- 1 | label('User Profiles'); 14 | $config->setName('profiles'); 15 | 16 | $table->increments('id'); 17 | $table->belongsTo('users', 'user'); 18 | $table->string('first_name')->nullable(); 19 | $table->string('last_name')->nullable(); 20 | 21 | $table->file('avatar', 'sv/users/avatar'); 22 | $table->createdBy()->updatedBy(); 23 | $table->restorable(); 24 | }); 25 | } 26 | 27 | public function down() 28 | { 29 | Schema::dropIfExists('sv_profiles'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /database/migrations/2018_04_19_035358_create_media_table.php: -------------------------------------------------------------------------------- 1 | label('Media'); 14 | 15 | $config->setName('media'); 16 | 17 | $table->increments('id'); 18 | $table->morphTo('owner'); 19 | $table->string('disk')->showOnIndex(); 20 | $table->string('original')->showOnIndex(); 21 | $table->string('filename'); 22 | $table->string('mime_type'); 23 | $table->string('label')->showOnIndex(); 24 | $table->string('extension'); 25 | $table->unsignedInteger('size'); 26 | 27 | $table->createdBy()->updatedBy(); 28 | $table->restorable(); 29 | }); 30 | } 31 | 32 | public function down() 33 | { 34 | Schema::dropIfExists('sv_media'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/lang/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "Create": "Create", 3 | "Create New": "Create New :Object", 4 | "Select :Object": "Select :Object", 5 | "Save": "Save", 6 | "Select All": "Select All", 7 | "Remove All": "Remove All", 8 | ":Resource :Entry was updated": ":Resource [:Entry] was updated.", 9 | ":Resource :Entry was created": ":Resource [:Entry] was created.", 10 | ":Resource :Entry was deleted": ":Resource [:Entry] was deleted.", 11 | "Are you sure?": "Are you sure?", 12 | "You won't be able to revert this!": "You won't be able to revert this!", 13 | "Yes, delete it!": "Yes, delete it!", 14 | "Cancel": "Cancel", 15 | "Forms": "Forms", 16 | "Auth": "Auth" 17 | } 18 | -------------------------------------------------------------------------------- /resources/lang/tr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Yes": "Evet", 3 | "No": "Hayır", 4 | "Active": "Aktif", 5 | "All": "Tümü", 6 | "View": "Detaylar", 7 | "Edit": "Düzenle", 8 | "Created": "Oluşturuldu", 9 | "Updated": "Güncellendi", 10 | "Deleted": "Silindi", 11 | "Search": "Ara", 12 | "No results found": "Hiç sonuç bulunamadı", 13 | "Upload": "Yükle", 14 | "Create": "Oluştur", 15 | "Create New": "Yeni :Object Oluştur", 16 | "Save": "Kaydet", 17 | "Select :Object": ":Object Seç", 18 | "Select All": "Tümünü Seç", 19 | "Remove All": "Tümünü Kaldır", 20 | ":Entry was updated": "[:Entry] güncellendi.", 21 | ":Entry was created": "[:Entry] oluşturuldu.", 22 | ":Entry was deleted": "[:Entry] silindi.", 23 | "Are you sure?": "Emin misiniz?", 24 | "You won't be able to revert this!": "Bunu geri alma imkanınız olmayabilir!", 25 | "Yes, delete it!": "Evet, sil!", 26 | "Cancel": "İptal", 27 | "Attach": "Ekle", 28 | "Detach": "Kaldır", 29 | "System": "Sistem", 30 | "Email": "E-Posta", 31 | "Password": "Şifre", 32 | "Resources": "Kaynaklar", 33 | "Forms": "Formlar", 34 | "Auth": "Auth", 35 | "Showing :num Records": ":num kayıt gösteriliyor", 36 | "Login successful": "Giriş başarılı", 37 | "Invalid credentials": "Hatalı şifre/email kombinasyonu" 38 | } 39 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/.eslintrc.js.stub: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | amd: true, 4 | }, 5 | extends: ['plugin:vue/essential', 'eslint:recommended', 'prettier'], 6 | plugins: ['prettier', 'vue'], 7 | rules: { 8 | 'prettier/prettier': [ 9 | 'error', 10 | { 11 | semi: false, 12 | singleQuote: true, 13 | trailingComma: 'all', 14 | }, 15 | ], 16 | 'vue/require-v-for-key': 'off', 17 | 'vue/script-indent': 'off', 18 | eqeqeq: ['error', 'always'], 19 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 20 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 21 | }, 22 | parserOptions: { 23 | parser: 'babel-eslint', 24 | ecmaVersion: 2017, 25 | sourceType: 'module', 26 | }, 27 | globals: { 28 | IS_DEV: true, 29 | Config: true, 30 | process: true, 31 | module: true, 32 | __dirname: true, 33 | APP_ENV: true, 34 | }, 35 | } 36 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | *.lock 23 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/babel.config.js.stub: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/cli-plugin-babel/preset'], 3 | } 4 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/package.json.stub: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{addon.vendor}-{addon.name}", 3 | "private": true, 4 | "scripts": { 5 | "serve": "vue-cli-service serve", 6 | "build": "vue-cli-service build" 7 | }, 8 | "dependencies": { 9 | "@superv/ui": "^{platform.version}", 10 | "tailwindcss": "^1.1.3", 11 | "core-js": "^3.3.2", 12 | "vue": "^2.6.10" 13 | }, 14 | "devDependencies": { 15 | "@fullhuman/postcss-purgecss": "^1.3.0", 16 | "@vue/cli-plugin-babel": "^4.0.0", 17 | "@vue/cli-service": "^4.0.0", 18 | "vue-template-compiler": "^2.6.10" 19 | }, 20 | "browserslist": [ 21 | "> 1%", 22 | "last 2 versions" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/postcss.config.js.stub: -------------------------------------------------------------------------------- 1 | const purgecss = require('@fullhuman/postcss-purgecss')({ 2 | 3 | content: [ 4 | './src/**/*.html', 5 | './src/**/*.vue', 6 | './node_modules/@superv/ui/dist/superv-ui.umd.js' 7 | ], 8 | 9 | defaultExtractor: content => content.match(/[\w-/:]+(? 6 | 9 | 11 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/public/index.html.stub: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | {panel.label} Panel 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/src/Panel.vue.stub: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | 25 | 43 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/src/app/pages/Login.vue.stub: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/src/app/routes.js.stub: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | path: '/login', 4 | meta: { 5 | layout: 'blank', 6 | }, 7 | before: superv => { 8 | if (!superv.auth.loggedIn) { 9 | return true 10 | } 11 | superv.router().push('/') 12 | }, 13 | component: () => import('@app/pages/Login'), 14 | }, 15 | ] 16 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/src/main.js.stub: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import supervjs from '@superv/ui' 3 | import {panel.title} from './{panel.title}' 4 | import routes from './app/routes' 5 | import tools from '../../tools' 6 | 7 | let config = { apiUrl: '/api' } 8 | if (process.env.NODE_ENV !== 'development') { 9 | config = JSON.parse(document.getElementById('config').innerHTML) 10 | } 11 | 12 | Vue.config.productionTip = false 13 | Vue.use(supervjs, { 14 | config: { 15 | name: process.env.VUE_APP_PANEL_NAME, 16 | apiUrl: config.apiUrl, 17 | baseUrl: config.baseUrl, 18 | }, 19 | routes, 20 | tools, 21 | }) 22 | 23 | new Vue({ 24 | el: '#app', 25 | name: 'root', 26 | data() { 27 | return { 28 | layouts: { default: {panel.title} }, 29 | } 30 | }, 31 | mixins: [require('@superv/ui').LayoutMixin], 32 | }) 33 | -------------------------------------------------------------------------------- /resources/skeletons/panel/frontend/tailwind.config.js.stub: -------------------------------------------------------------------------------- 1 | const config = require('@superv/ui/tailwind.config.js') 2 | module.exports = { 3 | theme: config.theme, 4 | variants: config.variants, 5 | plugins: config.plugins, 6 | } 7 | -------------------------------------------------------------------------------- /resources/skeletons/panel/routes/global.php.stub: -------------------------------------------------------------------------------- 1 | [ 7 | 'uses' => {panel.title}Controller::class, 8 | 'where' => ['path' => '.*'], 9 | ], 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/skeletons/panel/src/Panel.php.stub: -------------------------------------------------------------------------------- 1 | '{addon.identifier}.assets', '--force' => true]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /resources/skeletons/panel/src/PanelController.php.stub: -------------------------------------------------------------------------------- 1 | getPort()) { 12 | return 'Please specify a port for this panel'; 13 | } 14 | 15 | return view('{addon.identifier}::panel', [ 16 | 'config' => [ 17 | 'apiUrl' => $port->url(), 18 | 'baseUrl' => '{panel.base_path}' 19 | ] 20 | ]); 21 | } 22 | } -------------------------------------------------------------------------------- /resources/skeletons/panel/src/PanelServiceProvider.php.stub: -------------------------------------------------------------------------------- 1 | assertNotNull(sv_addons('{addon.identifier}')); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /resources/stubs/addons/testing/TestCase.stub: -------------------------------------------------------------------------------- 1 | create('DummyTable', 12 | function (Blueprint $table, Config $config) { 13 | // $config->identifier(''); 14 | // $config->label(''); 15 | // $config->nav(''); 16 | // $config->resourceKey(''); 17 | 18 | $table->increments('id'); 19 | 20 | $table->createdBy(); 21 | $table->updatedBy(); 22 | }); 23 | } 24 | 25 | public function down() 26 | { 27 | $this->dropIfExists('DummyTable'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/stubs/generator/migration.stub: -------------------------------------------------------------------------------- 1 | run('{table_name}', 15 | function (Blueprint $table, Config $config) { 16 | {config} 17 | 18 | {blueprint} 19 | }); 20 | } 21 | 22 | public function down() 23 | { 24 | DeleteResource::dispatch('{resource}'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/stubs/update.stub: -------------------------------------------------------------------------------- 1 | table('DummyTable', function (Blueprint $table) { 11 | // 12 | }); 13 | } 14 | 15 | public function down() 16 | { 17 | $this->table('DummyTable', function (Blueprint $table) { 18 | // 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /routes/all-ports/all-ports.php: -------------------------------------------------------------------------------- 1 | [ 10 | 'as' => 'sv::data.init', 11 | 'uses' => DataController::class.'@init', 12 | ], 13 | 'sv/data/nav' => [ 14 | 'as' => 'sv::data.nav', 15 | 'uses' => DataController::class.'@nav', 16 | ], 17 | 'post@sv/login' => [ 18 | 'as' => 'sv.login', 19 | 'uses' => AuthController::class.'@login', 20 | ], 21 | 'sv/platform' => function () { 22 | return 'SuperV Platform @'.Current::port()->slug(); 23 | }, 24 | 25 | 'GET@'.'sv/wake/{uuid}' => WakeupController::at('get'), 26 | ]; 27 | -------------------------------------------------------------------------------- /routes/all-ports/entry-routes.php: -------------------------------------------------------------------------------- 1 | [ 5 | // 'as' => 'entry.show', 6 | // 'uses' => EntryController::at('show'), 7 | // ], 8 | 9 | ]; -------------------------------------------------------------------------------- /src/Adapters/AdapterServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind(Dispatcher::class, LaravelDispatcher::class); 15 | $this->app->bind(Validator::class, LaravelValidator::class); 16 | $this->app->bind(Filesystem::class, LaravelFileSystem::class); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Adapters/LaravelDispatcher.php: -------------------------------------------------------------------------------- 1 | dispatcher = $dispatcher; 17 | } 18 | 19 | public function dispatch($event, $payload = []) 20 | { 21 | $this->dispatcher->dispatch($event, $payload); 22 | } 23 | 24 | public function listen($events, $listener) 25 | { 26 | $this->dispatcher->listen($events, $listener); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Adapters/LaravelFileSystem.php: -------------------------------------------------------------------------------- 1 | filter(function (Addon $addon) { 15 | return $addon->entry()->enabled; 16 | }); 17 | } 18 | 19 | public function slugs() 20 | { 21 | return $this->map(function (Addon $addon) { 22 | return $addon->getIdentifier(); 23 | })->values(); 24 | } 25 | 26 | public function identifiers() 27 | { 28 | return $this->map(function (Addon $addon) { 29 | return $addon->getIdentifier(); 30 | })->values(); 31 | } 32 | 33 | public function withSlug(string $slug): ?Addon 34 | { 35 | foreach ($this->items as $key => $addon) { 36 | if ($slug === $key) { 37 | return $addon; 38 | } 39 | } 40 | } 41 | 42 | public function withClass(string $class): ?Addon 43 | { 44 | foreach ($this->items as $key => $addon) { 45 | if ($class === get_class($addon)) { 46 | return $addon; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Domains/Addon/Console/AddonReinstallCommand.php: -------------------------------------------------------------------------------- 1 | option('identifier')) { 16 | if ($addons->enabled()->isEmpty()) { 17 | return $this->warn('There are no addons currently installed'); 18 | } 19 | $identifier = $this->choice('Select Addon to Reinstall', $addons->enabled()->identifiers()->all()); 20 | } 21 | 22 | try { 23 | $addon = $addons->withSlug($identifier); 24 | 25 | $this->call('addon:uninstall', ['--identifier' => $identifier]); 26 | 27 | $this->call('addon:install', [ 28 | 'path' => $addon->path(), 29 | '--seed' => $this->option('seed'), 30 | ]); 31 | } catch (Exception $e) { 32 | $this->error($e->getMessage()); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Domains/Addon/Console/AddonRunMigrationCommand.php: -------------------------------------------------------------------------------- 1 | option('addon')) { 14 | $addon = $this->choice('Select Addon to Run Migrations', sv_addons()->enabled()->slugs()->all()); 15 | } 16 | 17 | $this->call('migrate', ['--namespace' => $addon]); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Domains/Addon/Console/AddonUninstallCommand.php: -------------------------------------------------------------------------------- 1 | option('identifier')) { 16 | $identifier = $this->choice('Select Addon to Uninstall', $addons->enabled()->slugs()->all()); 17 | } 18 | $this->comment(sprintf('Uninstalling %s', $identifier)); 19 | 20 | if ($this->dispatch(new UninstallAddonJob($identifier))) { 21 | $this->info('The ['.$identifier.'] addon successfully uninstalled.'); 22 | } else { 23 | $this->error('Addon could not be uninstalled'); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Console/MakeAddonCommand.php: -------------------------------------------------------------------------------- 1 | argument('identifier'), 17 | $this->option('type') 18 | ); 19 | 20 | if ($this->hasOption('path')) { 21 | $request->setTargetPath($this->option('path')); 22 | } 23 | 24 | MakeAddon::dispatch($request, $this->option('force')); 25 | 26 | $this->info('The ['.$this->argument('identifier').'] addon was created.'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Domains/Addon/Console/MakeModuleCommand.php: -------------------------------------------------------------------------------- 1 | call('make:addon', [ 14 | 'identifier' => $this->argument('identifier'), 15 | '--type' => 'module', 16 | '--path' => $this->option('path'), 17 | '--force' => $this->option('force'), 18 | ]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Domains/Addon/Console/MakePanelCommand.php: -------------------------------------------------------------------------------- 1 | argument('identifier'), 17 | 'panel' 18 | ); 19 | 20 | if ($this->hasOption('path')) { 21 | $request->setTargetPath($this->option('path')); 22 | } 23 | 24 | MakeAddon::dispatch($request, $this->option('force')); 25 | 26 | $this->info('The ['.$this->argument('identifier').'] panel was created.'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Domains/Addon/Contracts/AddonLocator.php: -------------------------------------------------------------------------------- 1 | addon = $addon; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Events/AddonInstalledEvent.php: -------------------------------------------------------------------------------- 1 | addon = $addon; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Events/AddonUninstallingEvent.php: -------------------------------------------------------------------------------- 1 | addon = $addon; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Events/MakingAddonEvent.php: -------------------------------------------------------------------------------- 1 | addon = $addon; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Features/MakeAddon.php: -------------------------------------------------------------------------------- 1 | request = $request; 29 | $this->force = $force; 30 | } 31 | 32 | public function handle() 33 | { 34 | $model = MakeAddonModel::makeFromRequest($this->request); 35 | 36 | CreateAddonPaths::dispatch($model, $this->force); 37 | CreateAddonFiles::dispatch($model); 38 | MakingAddonEvent::dispatch($model); 39 | 40 | exec("composer install -d ".base_path()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Domains/Addon/Jobs/EnableConfigFiles.php: -------------------------------------------------------------------------------- 1 | addon = $addon; 17 | } 18 | 19 | public function handle() 20 | { 21 | foreach (glob($this->addon->path('config/*')) as $path) { 22 | $key = pathinfo($path, PATHINFO_FILENAME); 23 | $config = config()->get("superv.{$key}", []); 24 | 25 | $fromModule = require $path; 26 | $merged = array_replace_recursive($fromModule, $config); 27 | 28 | config()->set($this->addon->getIdentifier().'::'.$key, $merged); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Domains/Addon/Jobs/SeedAddon.php: -------------------------------------------------------------------------------- 1 | addon = $addon; 20 | } 21 | 22 | public function handle() 23 | { 24 | $seederClass = $this->addon->seederClass(); 25 | 26 | if (class_exists($seederClass)) { 27 | app()->make($seederClass, ['addon' => $this->addon])->seed(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Jobs/UninstallAddonJob.php: -------------------------------------------------------------------------------- 1 | addon = $addon; 22 | } 23 | 24 | public function handle(AddonCollection $addons) 25 | { 26 | if (is_string($this->addon)) { 27 | $this->addon = $addons->get($this->addon); 28 | } 29 | if (! $this->addon) { 30 | PlatformException::fail("Addon not found: ".$this->addon); 31 | } 32 | 33 | AddonUninstallingEvent::dispatch($this->addon); 34 | 35 | Artisan::call('migrate:reset', ['--namespace' => $this->addon->getIdentifier(), '--force' => true]); 36 | 37 | $this->addon->entry()->delete(); 38 | 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Domains/Addon/Listeners/AddonBootedListener.php: -------------------------------------------------------------------------------- 1 | addon; 12 | 13 | $addon->fire('booted'); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Listeners/AddonInstalledListener.php: -------------------------------------------------------------------------------- 1 | addon; 12 | 13 | // sv_resource('platform.namespaces')->create([ 14 | // 'namespace' => $addon->getIdentifier().'::resources', 15 | // 'type' => 'resource', 16 | // ]); 17 | 18 | superv('addons')->put($addon->getIdentifier(), $addon); 19 | 20 | $addon->boot(); 21 | 22 | $addon->fire('installed'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Domains/Addon/Locator.php: -------------------------------------------------------------------------------- 1 | addonsPath = $addonsPath; 17 | } 18 | 19 | public function locate(string $identifier, string $type) 20 | { 21 | list($vendor, $package) = array_map( 22 | function ($value) { 23 | return strtolower($value); 24 | }, 25 | explode('.', $identifier) 26 | ); 27 | 28 | $type = str_plural($type); 29 | 30 | return $this->addonsPath()."/{$vendor}/{$type}/{$package}"; 31 | } 32 | 33 | protected function addonsPath() 34 | { 35 | return $this->addonsPath ?: \Platform::config('addons.location'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Domains/Addon/Types/Droplet.php: -------------------------------------------------------------------------------- 1 | portSlug); 33 | } 34 | 35 | public static function make($addon): Panel 36 | { 37 | return sv_addons($addon); 38 | } 39 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Types/Panel/PanelServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishAssets(); 14 | } 15 | 16 | protected function publishAssets() 17 | { 18 | $vendor = $this->addon->getVendor(); 19 | $name = $this->addon->getName(); 20 | 21 | $this->publishes( 22 | [$this->addon->resourcePath('assets') => public_path(sprintf("vendor/%s/%s", $vendor, $name))], 23 | sprintf("%s.assets", $name) 24 | ); 25 | } 26 | } -------------------------------------------------------------------------------- /src/Domains/Addon/Types/Tool.php: -------------------------------------------------------------------------------- 1 | slug; 14 | } 15 | 16 | public static function withSlug($slug) 17 | { 18 | return static::where('slug', $slug)->first(); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Access/AuthorizationFailedException.php: -------------------------------------------------------------------------------- 1 | first(); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Account.php: -------------------------------------------------------------------------------- 1 | hasMany(config('superv.auth.user.model')); 15 | } 16 | 17 | public function getId() 18 | { 19 | return $this->id; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Concerns/AuthenticatesUsers.php: -------------------------------------------------------------------------------- 1 | guard('sv-api'); 12 | 13 | if (! $guard->attempt($request->only(['email', 'password']))) { 14 | return redirect()->back() 15 | ->withInput(request(['email'])) 16 | ->withErrors([ 17 | 'email' => 'Invalid credentials', 18 | ]); 19 | } 20 | 21 | return redirect()->to($this->redirectTo()); 22 | } 23 | 24 | public function redirectTo() 25 | { 26 | return $this->redirectTo ?? '/'; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Concerns/RegistersUsers.php: -------------------------------------------------------------------------------- 1 | setRequest(request()->all())->register(); 22 | 23 | return redirect()->to($this->getRedirectTo()); 24 | } 25 | 26 | public function getRedirectTo() 27 | { 28 | return $this->redirectTo; 29 | } 30 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Console/AssignRoleCommand.php: -------------------------------------------------------------------------------- 1 | where('email', $this->argument('email'))->firstOrFail(); 18 | 19 | $user->assign($this->argument('role')); 20 | 21 | $roles = implode(',', $user->roles->pluck('slug')->toArray()); 22 | 23 | $this->comment("Current roles: [{$roles}] "); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Console/SuperVUserCommand.php: -------------------------------------------------------------------------------- 1 | withEmail($this->argument('email'))) { 17 | $user->updatePassword($this->getPassword()); 18 | } else { 19 | $user = app(Users::class)->create([ 20 | 'name' => $this->argument('name'), 21 | 'email' => $this->argument('email'), 22 | 'password' => bcrypt($this->getPassword()), 23 | ]); 24 | } 25 | 26 | $user->assign($this->option('role')); 27 | 28 | $user->allow('*'); 29 | 30 | $this->comment("User created and allowed all (*) with ID: {$user->id}"); 31 | } 32 | 33 | /** 34 | * @return array|mixed|string|null 35 | */ 36 | protected function getPassword() 37 | { 38 | return $this->option('password') ?? $this->ask('Enter user password'); 39 | } 40 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Contracts/Account.php: -------------------------------------------------------------------------------- 1 | user = $user; 25 | $this->request = $request; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Domains/Auth/JWTGuard.php: -------------------------------------------------------------------------------- 1 | user !== null) { 13 | return $this->user; 14 | } 15 | 16 | if ($this->jwt->setRequest($this->request)->getToken() && 17 | ($payload = $this->jwt->check(true)) && 18 | $this->validateSubject() 19 | ) { 20 | if (! $payload->get('port') || $payload->get('port') === Current::port()->slug()) { 21 | return $this->user = $this->provider->retrieveById($payload['sub']); 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/Auth/Profile.php: -------------------------------------------------------------------------------- 1 | table = $config->getDriver()->getParam('table'); 39 | $this->column = $column; 40 | $this->model = $model; 41 | $this->blueprint = $blueprint; 42 | $this->config = $config; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Domains/Database/Events/ColumnDroppedEvent.php: -------------------------------------------------------------------------------- 1 | columnName = $columnName; 20 | $this->config = $config; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Domains/Database/Events/ColumnUpdatedEvent.php: -------------------------------------------------------------------------------- 1 | table = $config->getDriver()->getParam('table'); 34 | $this->column = $column; 35 | $this->blueprint = $blueprint; 36 | $this->config = $config; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Domains/Database/Events/TableCreatedEvent.php: -------------------------------------------------------------------------------- 1 | table = $table; 28 | $this->columns = $columns; 29 | $this->config = $config; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Domains/Database/Events/TableCreatingEvent.php: -------------------------------------------------------------------------------- 1 | table = $table; 38 | $this->columns = $columns; 39 | $this->config = $config; 40 | $this->namespace = $namespace; 41 | $this->blueprint = $blueprint; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Domains/Database/Events/TableDroppedEvent.php: -------------------------------------------------------------------------------- 1 | table = $table; 26 | $this->connection = $connection; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Domains/Database/Events/TableDroppingEvent.php: -------------------------------------------------------------------------------- 1 | table = $table; 26 | $this->connection = $connection; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Domains/Database/Events/TableInsertEvent.php: -------------------------------------------------------------------------------- 1 | table = $table; 19 | } 20 | } -------------------------------------------------------------------------------- /src/Domains/Database/Events/TableUpdateEvent.php: -------------------------------------------------------------------------------- 1 | table = $table; 21 | $this->rowId = $rowId; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Domains/Database/Jobs/BuildBlueprintJob.php: -------------------------------------------------------------------------------- 1 | option('namespace')) { 12 | if (in_array($command, ['migrate', 'migrate:rollback', 'migrate:reset'])) { 13 | array_set($arguments, '--namespace', $this->option('namespace')); 14 | } 15 | } 16 | 17 | return parent::call($command, $arguments); 18 | } 19 | 20 | public function getOptions() 21 | { 22 | return array_merge( 23 | parent::getOptions(), 24 | [ 25 | ['namespace', null, InputOption::VALUE_OPTIONAL, 'The namespace to rollback for.'], 26 | ] 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Domains/Database/Migrations/Console/ResetCommand.php: -------------------------------------------------------------------------------- 1 | option('namespace')) { 12 | $this->migrator->setNamespace($this->option('namespace')); 13 | } 14 | parent::handle(); 15 | } 16 | 17 | public function getOptions() 18 | { 19 | return array_merge( 20 | parent::getOptions(), 21 | [ 22 | ['namespace', null, InputOption::VALUE_OPTIONAL, 'The namespace to reset for.'], 23 | ] 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Domains/Database/Migrations/Console/RollbackCommand.php: -------------------------------------------------------------------------------- 1 | option('namespace')) { 15 | $this->migrator->setNamespace($this->option('namespace')); 16 | } 17 | parent::handle(); 18 | } 19 | 20 | public function getOptions() 21 | { 22 | return array_merge( 23 | parent::getOptions(), 24 | [ 25 | ['namespace', null, InputOption::VALUE_OPTIONAL, 'The namespace to rollback for.'], 26 | ] 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Domains/Database/Migrations/MigrationCreator.php: -------------------------------------------------------------------------------- 1 | namespace, $stub); 19 | } 20 | 21 | public function setNamespace($namespace): void 22 | { 23 | $this->namespace = $namespace; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/Database/Migrations/PlatformMigration.php: -------------------------------------------------------------------------------- 1 | namespace = $namespace; 22 | $this->identifier = $identifier; 23 | } 24 | 25 | public function resolve($data) 26 | { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Domains/Drop/Contracts/Drop.php: -------------------------------------------------------------------------------- 1 | create([ 17 | 'key' => $dropKey, 18 | 'repo_key' => $this->repoKey, 19 | ]); 20 | 21 | return $drop; 22 | } 23 | 24 | public function dropKey($dropKey): Factory 25 | { 26 | $this->dropKey = $dropKey; 27 | 28 | return $this; 29 | } 30 | 31 | public function setRepo(RepoHandler $repo): Factory 32 | { 33 | $this->repo = $repo; 34 | 35 | return $this; 36 | } 37 | 38 | public function repoKey($repoKey): Factory 39 | { 40 | $this->repoKey = $repoKey; 41 | 42 | return $this; 43 | } 44 | 45 | public static function repo($repoKey): Factory 46 | { 47 | return (new static)->repoKey($repoKey); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Domains/Mail/MailTemplate.php: -------------------------------------------------------------------------------- 1 | morphMany(Media::class, 'owner'); 16 | } 17 | 18 | public function addMedia($filePath, MediaOptions $options) 19 | { 20 | return $this->mediaBag($options->getLabel()) 21 | ->addFromPath($filePath, $options); 22 | } 23 | } -------------------------------------------------------------------------------- /src/Domains/Media/MediaOwner.php: -------------------------------------------------------------------------------- 1 | port = $port; 17 | } 18 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Action/Contracts/ActionContract.php: -------------------------------------------------------------------------------- 1 | merge([ 20 | 'url' => $this->getUrl(), 21 | 'button' => [ 22 | 'color' => 'green', 23 | 'size' => 'sm', 24 | 'title' => __('Create'), 25 | ], 26 | ]); 27 | } 28 | 29 | public function setUrl($url) 30 | { 31 | $this->url = $url; 32 | 33 | return $this; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | protected function getUrl(): string 40 | { 41 | return $this->url; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Domains/Resource/Action/EditEntryAction.php: -------------------------------------------------------------------------------- 1 | set('url', $this->getUrl()); 22 | $payload->set('button', [ 23 | 'title' => '', 24 | // 'color' => 'primary inverse', 25 | 'icon' => 'edit', 26 | 'size' => 'sm', 27 | ]); 28 | } 29 | 30 | public function getUrl() 31 | { 32 | return $this->url; 33 | } 34 | 35 | public function setUrl($url) 36 | { 37 | $this->url = $url; 38 | 39 | return $this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Domains/Resource/Action/ModalAction.php: -------------------------------------------------------------------------------- 1 | set('url', $this->modalUrl); 17 | } 18 | 19 | public function makeComponent(): ComponentContract 20 | { 21 | return parent::makeComponent() 22 | ->setName('sv-modal-action') 23 | ->setProp('identifier', $this->identifier) 24 | ->setProp('button', [ 25 | 'color' => 'sky', 26 | 'size' => 'sm', 27 | 'title' => $this->title, 28 | ]); 29 | } 30 | 31 | public function setModalUrl($modalUrl) 32 | { 33 | $this->modalUrl = $modalUrl; 34 | 35 | return $this; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Action/RequestAction.php: -------------------------------------------------------------------------------- 1 | requestUrl; 14 | } 15 | 16 | public function setRequestUrl($requestUrl): void 17 | { 18 | $this->requestUrl = $requestUrl; 19 | } 20 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Action/ResourceEntryAction.php: -------------------------------------------------------------------------------- 1 | resource = $resource; 21 | } 22 | 23 | public function setEntry(EntryContract $entry) 24 | { 25 | $this->entry = $entry; 26 | } 27 | 28 | public function getRequestUrl() 29 | { 30 | return $this->entry->router()->actions($this->getName()); 31 | } 32 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Action/ViewEntryAction.php: -------------------------------------------------------------------------------- 1 | set('url', $this->getUrl()); 20 | $payload->set('button', [ 21 | 'title' => '', 22 | // 'color' => 'primary inverse', 23 | 'icon' => 'view', 24 | 'size' => 'sm', 25 | ]); 26 | } 27 | 28 | public function getUrl() 29 | { 30 | return $this->url; 31 | } 32 | 33 | public function setUrl($url) 34 | { 35 | $this->url = $url; 36 | 37 | return $this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Domains/Resource/Contracts/AcceptsEntry.php: -------------------------------------------------------------------------------- 1 | table = $table; 12 | } 13 | 14 | /** 15 | * Create a new instance of the given model. 16 | * 17 | * @param array $attributes 18 | * @param bool $exists 19 | * @return static 20 | */ 21 | public function newInstance($attributes = [], $exists = false) 22 | { 23 | // This method just provides a convenient way for us to generate fresh model 24 | // instances of this current model. It is particularly useful during the 25 | // hydration of new objects via the Eloquent query builder instances. 26 | $model = new static((array)$attributes); 27 | 28 | $model->exists = $exists; 29 | 30 | $model->setConnection( 31 | $this->getConnectionName() 32 | ); 33 | 34 | $model->setTable($this->getTable()); 35 | $model->setKeyName($this->getKeyName()); 36 | $model->setResourceIdentifier($this->getResourceIdentifier()); 37 | 38 | return $model; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Domains/Resource/Database/Entry/DatabaseEntry.php: -------------------------------------------------------------------------------- 1 | entry = $entry; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Database/Entry/Events/EntryCreatingEvent.php: -------------------------------------------------------------------------------- 1 | entry = $entry; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Database/Entry/Events/EntryDeletedEvent.php: -------------------------------------------------------------------------------- 1 | entry = $entry; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Database/Entry/Events/EntryRetrievedEvent.php: -------------------------------------------------------------------------------- 1 | entry = $entry; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Database/Entry/Events/EntrySavedEvent.php: -------------------------------------------------------------------------------- 1 | entry = $entry; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Database/Entry/Events/EntrySavingEvent.php: -------------------------------------------------------------------------------- 1 | entry = $entry; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Database/ResourceRepository.php: -------------------------------------------------------------------------------- 1 | model = $model; 18 | } 19 | 20 | public function create(ResourceConfig $config) 21 | { 22 | $attributes = [ 23 | 'uuid' => uuid(), 24 | 'name' => $config->getName(), 25 | 'namespace' => $config->getNamespace(), 26 | 'identifier' => $config->getNamespace().'.'.$config->getName(), 27 | 'dsn' => $config->getDriver()->toDsn(), 28 | 'model' => $config->getModel(), 29 | 'config' => $config->toArray(), 30 | 'restorable' => (bool)$config->isRestorable(), 31 | 'sortable' => (bool)$config->isSortable(), 32 | ]; 33 | 34 | return $this->model->newQuery()->create($attributes); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Domains/Resource/Events/ResourceConfigResolvedEvent.php: -------------------------------------------------------------------------------- 1 | config = $config; 20 | } 21 | 22 | /** 23 | * @return \SuperV\Platform\Domains\Resource\ResourceConfig 24 | */ 25 | public function config(): \SuperV\Platform\Domains\Resource\ResourceConfig 26 | { 27 | return $this->config; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Domains/Resource/Events/ResourceCreatedEvent.php: -------------------------------------------------------------------------------- 1 | resourceEntry = $resourceEntry; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Domains/Resource/Extension/Contracts/ExtendsMultipleResources.php: -------------------------------------------------------------------------------- 1 | path = $path; 25 | $this->baseNamespace = $baseNamespace; 26 | } 27 | 28 | public function handle() 29 | { 30 | if (! file_exists($this->path)) { 31 | return; 32 | } 33 | 34 | $searchIn = array_merge( 35 | glob($this->path.'/*Extension.php'), 36 | glob($this->path.'/**/*Extension.php') 37 | ); 38 | 39 | /** 40 | * register resources and navigations 41 | */ 42 | if (! empty($searchIn)) { 43 | foreach ($searchIn as $file) { 44 | $class = Path::parseClass($this->baseNamespace, $this->path, $file); 45 | Extension::register($class); 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Features/UserType.php: -------------------------------------------------------------------------------- 1 | assign('user'); 15 | $entry->assign($role); 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Accessor.php: -------------------------------------------------------------------------------- 1 | accessible = $accessible; 17 | } 18 | 19 | public function get(array $params = []) 20 | { 21 | $callback = $this->accessible->getAccessor(); 22 | 23 | return app()->call($callback, $params); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Contracts/AltersDatabaseTable.php: -------------------------------------------------------------------------------- 1 | field->getFieldType(); 18 | 19 | if (! $fieldType instanceof SortsQuery) { 20 | return; 21 | } 22 | 23 | $fieldType->sortQuery($this->query, $direction); 24 | } 25 | 26 | public function setQuery($query) 27 | { 28 | $this->query = $query; 29 | } 30 | 31 | /** 32 | * @param \SuperV\Platform\Domains\Resource\Field\Contracts\FieldInterface $field 33 | */ 34 | public function setField(\SuperV\Platform\Domains\Resource\Field\Contracts\FieldInterface $field): void 35 | { 36 | $this->field = $field; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/GhostField.php: -------------------------------------------------------------------------------- 1 | modifible = $modifible; 17 | } 18 | 19 | public function set(array $params = []) 20 | { 21 | $callback = $this->modifible->getModifier(); 22 | 23 | return app()->call($callback, $params); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Rules.php: -------------------------------------------------------------------------------- 1 | rules[$parts[0]] = true; 18 | } else { 19 | $this->rules[$parts[0]] = $parts[1]; 20 | } 21 | } 22 | 23 | return $this; 24 | } 25 | 26 | public function setRule($rule, $params): self 27 | { 28 | $this->rules[$rule] = $params; 29 | 30 | return $this; 31 | } 32 | 33 | public function get(array $params = []) 34 | { 35 | $rules = []; 36 | foreach ($this->rules as $key => $value) { 37 | if (is_bool($value)) { 38 | $rules[] = $key; 39 | } else { 40 | $rules[] = $key.':'.($params ? sv_parse($value, $params) : $value); 41 | } 42 | } 43 | 44 | return $rules; 45 | } 46 | 47 | public static function make(array $rules): self 48 | { 49 | return (new static)->merge($rules); 50 | } 51 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Rules/HumanNameRule.php: -------------------------------------------------------------------------------- 1 | orderBy($this->field->getColumnName(), $direction); 17 | } 18 | 19 | public function getAccessor(): Closure 20 | { 21 | return function ($value) { 22 | return ($value === 'false' || ! $value) ? false : true; 23 | }; 24 | } 25 | 26 | public function getModifier(): Closure 27 | { 28 | return function ($value) { 29 | return ($value === 'false' || ! $value) ? false : true; 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/CheckboxField.php: -------------------------------------------------------------------------------- 1 | orderBy($this->field->getColumnName(), $direction); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/EncryptedField.php: -------------------------------------------------------------------------------- 1 | set('value', null); 18 | } 19 | 20 | public function resolveDataFromRequest(FormData $data, Request $request, ?EntryContract $entry = null) 21 | { 22 | if (! $value = $request->get($this->getName())) { 23 | return null; 24 | } 25 | 26 | $data->set($this->getColumnName(), bcrypt($value)); 27 | } 28 | 29 | public function updateRules(FieldRules $rules) 30 | { 31 | $rules->addRule('sometimes'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/ModalFormField.php: -------------------------------------------------------------------------------- 1 | field->on('form.composing', $this->composer()); 13 | } 14 | 15 | protected function composer() 16 | { 17 | return function (Payload $payload) { 18 | $payload->set('config.form', $this->getConfigValue('form')); 19 | }; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/Polymorphic/PolymorphicField.php: -------------------------------------------------------------------------------- 1 | getTypes() as $typeName => $callback) { 18 | $callback = function (Blueprint $table, ResourceConfig $resourceConfig) use ($config, $callback) { 19 | $table->belongsTo($config->getSelf()); 20 | $callback($table, $resourceConfig); 21 | }; 22 | 23 | Schema::create($config->getSelf().'_'.$typeName, $callback); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/Polymorphic/PolymorphicFieldConfig.php: -------------------------------------------------------------------------------- 1 | types[$typeName] = $callback; 15 | 16 | return $this; 17 | } 18 | 19 | /** 20 | * @return array 21 | */ 22 | public function getTypes(): array 23 | { 24 | return $this->types; 25 | } 26 | 27 | public static function make() 28 | { 29 | return new static; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/Relation/RelationType.php: -------------------------------------------------------------------------------- 1 | equals(static::oneToMany()); 16 | } 17 | 18 | public function isManyToMany(): bool 19 | { 20 | return $this->equals(static::manyToMany()); 21 | } 22 | 23 | public function isOneToOne(): bool 24 | { 25 | return $this->equals(static::oneToOne()); 26 | } 27 | 28 | public static function oneToMany(): self 29 | { 30 | return new static(self::ONE_TO_MANY); 31 | } 32 | 33 | public static function oneToOne(): self 34 | { 35 | return new static(self::ONE_TO_ONE); 36 | } 37 | 38 | public static function manyToMany(): self 39 | { 40 | return new static(self::MANY_TO_MANY); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/TextField.php: -------------------------------------------------------------------------------- 1 | getConfigValue('length')) { 16 | return ["max:{$length}"]; 17 | } 18 | } 19 | 20 | public function makeFilter(?array $params = []) 21 | { 22 | return DistinctFilter::make($this->getName()); 23 | } 24 | 25 | public function sortQuery($query, $direction) 26 | { 27 | $query->orderBy($this->field->getColumnName(), $direction); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Domains/Resource/Field/Types/TextareaField.php: -------------------------------------------------------------------------------- 1 | field->on('form.composing', $this->composer()); 14 | } 15 | 16 | protected function composer() 17 | { 18 | return function (Payload $payload) { 19 | if ($this->getConfigValue('rich') === true) { 20 | $payload->set('meta.rich', true); 21 | } 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Domains/Resource/Filter/BooleanFilter.php: -------------------------------------------------------------------------------- 1 | request = $request; 22 | $this->key = $key; 23 | } 24 | 25 | public function handle() 26 | { 27 | $value = $this->request->get($this->key); 28 | 29 | if ($decoded = base64_decode($value)) { 30 | if ($hydrated = json_decode($decoded, true)) { 31 | if (is_array($hydrated)) { 32 | return $hydrated; 33 | } 34 | } 35 | } 36 | 37 | return null; 38 | } 39 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Filter/DistinctFilter.php: -------------------------------------------------------------------------------- 1 | resource->newQuery() 10 | ->select($this->getIdentifier()) 11 | ->distinct() 12 | ->where($this->getIdentifier(), '!=', null) 13 | ->get() 14 | ->pluck($this->getIdentifier(), $this->getIdentifier()) 15 | ->all(); 16 | } 17 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Filter/SelectFilter.php: -------------------------------------------------------------------------------- 1 | setConfigValue('options', $this->getOptions()); 16 | $field->setConfigValue('placeholder', $this->getLabel()); 17 | } 18 | 19 | public function getOptions(): array 20 | { 21 | return $this->options; 22 | } 23 | 24 | public function setOptions(array $options): Filter 25 | { 26 | $this->options = $options; 27 | 28 | return $this; 29 | } 30 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Form/Contracts/FormBuilderInterface.php: -------------------------------------------------------------------------------- 1 | row = $row; 12 | 13 | return $this; 14 | } 15 | 16 | public static function make() 17 | { 18 | return new static; 19 | } 20 | 21 | public static function atRow($row) 22 | { 23 | return static::make()->setRow($row); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Hook/Actions/RegisterAddonHooks.php: -------------------------------------------------------------------------------- 1 | addon->realPath('src/Resources'); 13 | if (! file_exists($hooksPath)) { 14 | return; 15 | } 16 | 17 | HookManager::resolve()->scan($hooksPath); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Hook/Contracts/AfterCreatedHook.php: -------------------------------------------------------------------------------- 1 | FormResolvingHook::class, 13 | 'resolved' => FormResolvedHook::class, 14 | 'validating' => FormValidatingHook::class, 15 | ]; 16 | 17 | protected $hookType = 'forms'; 18 | } 19 | -------------------------------------------------------------------------------- /src/Domains/Resource/Hook/ObserverHookHandler.php: -------------------------------------------------------------------------------- 1 | BeforeCreatingHook::class, 16 | 'created' => AfterCreatedHook::class, 17 | 'saving' => BeforeSavingHook::class, 18 | 'saved' => AfterSavedHook::class, 19 | 'retrieved' => AfterRetrievedHook::class, 20 | 'deleted' => AfterDeletedHook::class, 21 | ]; 22 | 23 | protected $hookType = 'entry'; 24 | 25 | protected static $locks = []; 26 | } 27 | -------------------------------------------------------------------------------- /src/Domains/Resource/Hook/PagesHookHandler.php: -------------------------------------------------------------------------------- 1 | PageResolvedHook::class, 12 | 'rendered' => PageRenderedHook::class, 13 | ]; 14 | 15 | protected $hookType = 'pages'; 16 | } 17 | -------------------------------------------------------------------------------- /src/Domains/Resource/Hook/ResourceHookHandler.php: -------------------------------------------------------------------------------- 1 | ResourceResolvedHook::class, 13 | 'config_resolved' => ConfigResolvedHook::class, 14 | 'query_resolved' => QueryResolvedHook::class, 15 | ]; 16 | 17 | public function hook(string $identifier, string $hookHandler, string $subKey = null) 18 | { 19 | $implements = class_implements($hookHandler); 20 | 21 | foreach ($this->map as $eventType => $contract) { 22 | if (! in_array($contract, $implements)) { 23 | continue; 24 | } 25 | $eventName = sprintf("%s.events:%s", $identifier, $eventType); 26 | 27 | $this->registerListener($eventName, $eventType, $hookHandler); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Domains/Resource/Hook/ScopesHookHandler.php: -------------------------------------------------------------------------------- 1 | dispatcher->listen( 14 | $eventName, 15 | function () use ($hookHandler, $subKey) { 16 | $this->handle($hookHandler, $subKey, func_get_args()); 17 | } 18 | ); 19 | } 20 | 21 | protected function handle($hookHandler, $subKey, $payload) 22 | { 23 | if (! Current::hasUser()) { 24 | return; 25 | } 26 | 27 | if (! Current::user()->isA($role = $subKey)) { 28 | return; 29 | } 30 | 31 | if (is_string($hookHandler)) { 32 | $hookHandler = app($hookHandler); 33 | } 34 | 35 | $payload[] = Current::user(); 36 | 37 | $hookHandler->scope(...$payload); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Domains/Resource/Http/Controllers/Dashboard/ResourceDashboardController.php: -------------------------------------------------------------------------------- 1 | resolveResource(); 17 | 18 | $canList = Current::user()->can($resource->getChildIdentifier('actions', 'list')); 19 | $canCreate = Current::user()->can($resource->getChildIdentifier('actions', 'create')); 20 | 21 | if (! $canList && ! $canCreate) { 22 | abort(403); 23 | } 24 | 25 | $section = $this->route->parameter('section'); 26 | 27 | return ResourceDashboard::resolve($resource, $section) 28 | ->render(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Domains/Resource/Http/Controllers/Relation/RelationIndexController.php: -------------------------------------------------------------------------------- 1 | resolveRelation(); 18 | 19 | if (! $relation instanceof ProvidesTable) { 20 | throw new PlatformException('This relation does not provide a table'); 21 | } 22 | $table = $relation->makeTable(); 23 | 24 | if ($this->route->parameter('data')) { 25 | return $table->setRequest($this->request)->build(); 26 | } 27 | 28 | return MakeComponentTree::dispatch($table)->withTokens(['res' => $relation->getRelatedResource()->toArray()]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Domains/Resource/Http/Controllers/ResourceController.php: -------------------------------------------------------------------------------- 1 | resolveResource(); 15 | 16 | $this->entry->delete(); 17 | 18 | $message = __(':Entry was deleted', ['Entry' => $resource->getEntryLabel($this->entry)]); 19 | 20 | return ['data' => ['message' => $message]]; 21 | } 22 | 23 | public function restore() 24 | { 25 | $resource = $this->resolveResource(false); 26 | 27 | /** @var \SuperV\Platform\Domains\Resource\Database\Entry\ResourceEntry $entry */ 28 | $entry = $resource->newQuery()->withTrashed()->find(request()->route()->parameter('id')); 29 | 30 | $entry->restore(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Domains/Resource/Http/Controllers/ResourceViewController.php: -------------------------------------------------------------------------------- 1 | resolveResource(); 16 | 17 | return MakeComponentTree::dispatch($resource->resolveView($this->entry)); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Http/Middleware/WatchActivity.php: -------------------------------------------------------------------------------- 1 | where('namespace', 'platform')->get(); 16 | 17 | $platformResources->map(function (ResourceModel $model) { 18 | if ($model->getIdentifier() === 'platform.users') { 19 | return; 20 | } 21 | FormRepository::createForResource($model->getIdentifier()); 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Domains/Resource/Jobs/DeleteAddonResources.php: -------------------------------------------------------------------------------- 1 | addon; 15 | 16 | ResourceModel::query() 17 | ->where('namespace', $addon->getIdentifier()) 18 | ->get()->map(function (ResourceModel $resource) { 19 | DeleteResource::dispatch($resource); 20 | }); 21 | 22 | Section::query() 23 | ->where('namespace', $addon->getIdentifier()) 24 | ->get()->map->delete(); 25 | 26 | Action::query()->where('namespace', $addon->getIdentifier())->delete(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Domains/Resource/Jobs/GetTableResource.php: -------------------------------------------------------------------------------- 1 | table = $table; 27 | $this->connection = $connection; 28 | } 29 | 30 | public function handle() 31 | { 32 | $dsn = sprintf("%s@%s://%s", 'database', $this->connection, $this->table); 33 | if (! isset(static::$cache[$dsn])) { 34 | $identifier = DB::table('sv_resources')->where('dsn', $dsn)->value('identifier'); 35 | 36 | static::$cache[$dsn] = $identifier ?? false; 37 | } 38 | 39 | return static::$cache[$dsn]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Domains/Resource/Listeners/CreateResourceForm.php: -------------------------------------------------------------------------------- 1 | table; 19 | if (starts_with($table, 'sv_')) { 20 | return; 21 | } 22 | 23 | FormRepository::createForResource($event->config->getIdentifier()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Domains/Resource/Listeners/DeleteField.php: -------------------------------------------------------------------------------- 1 | config->getIdentifier())) { 13 | return; 14 | } 15 | 16 | if ($field = $resourceEntry->getField($event->columnName)) { 17 | $field->delete(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Domains/Resource/Listeners/RegisterExtensions.php: -------------------------------------------------------------------------------- 1 | addon->realPath('src/Extensions'), 14 | $event->addon->getPsrNamespace().'\Extensions' 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Domains/Resource/Listeners/SaveCreatedBy.php: -------------------------------------------------------------------------------- 1 | entry; 15 | 16 | if (! Resource::exists($entry)) { 17 | return; 18 | } 19 | 20 | $resource = ResourceFactory::make($entry); 21 | 22 | if ($resource->fields()->find('created_by')) { 23 | if ($user = auth()->user()) { 24 | $entry->created_by_id = $user->id; 25 | } elseif (Current::isConsole()) { 26 | $entry->created_by_id = 0; 27 | } 28 | } 29 | 30 | if ($resource->fields()->find('created_at')) { 31 | $entry->setAttribute('created_at', Current::time()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Domains/Resource/Listeners/SaveUpdatedBy.php: -------------------------------------------------------------------------------- 1 | entry; 15 | 16 | if (! Resource::exists($entry)) { 17 | return; 18 | } 19 | 20 | $resource = ResourceFactory::make($entry); 21 | 22 | if ($resource->fields()->has('updated_by')) { 23 | if ($user = auth()->user()) { 24 | $entry->updated_by_id = $user->id; 25 | } elseif (Current::isConsole()) { 26 | $entry->updated_by_id = 0; 27 | } 28 | } 29 | 30 | if ($resource->fields()->find('updated_at')) { 31 | $entry->setAttribute('updated_at', Current::time()); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Relation/Actions/AttachEntriesAction.php: -------------------------------------------------------------------------------- 1 | count()); 16 | } 17 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Relation/Contracts/ProvidesField.php: -------------------------------------------------------------------------------- 1 | type); 25 | if (! class_exists($class)) { 26 | throw new PlatformException("Relation class not found for type ".$entry->type); 27 | } 28 | 29 | return $class::fromEntry($entry); 30 | } 31 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Repository.php: -------------------------------------------------------------------------------- 1 | resource = $resource; 15 | } 16 | 17 | 18 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Resource/Extender.php: -------------------------------------------------------------------------------- 1 | identifier = $identifier; 24 | } 25 | 26 | public function extend(Resource $resource) 27 | { 28 | ($this->callback)($resource); 29 | } 30 | 31 | public function extends(): string 32 | { 33 | return $this->identifier; 34 | } 35 | 36 | public function with(Closure $callback) 37 | { 38 | $this->callback = $callback; 39 | 40 | return $this; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Domains/Resource/Resource/LabelConcern.php: -------------------------------------------------------------------------------- 1 | config()->getLabel(); 17 | } 18 | 19 | public function getEntryLabel(EntryContract $entry) 20 | { 21 | return sv_parse($this->config()->getEntryLabel(), $entry->toArray()); 22 | } 23 | 24 | public function getSingularLabel($translated = true) 25 | { 26 | if (! $singularLabel = $this->config()->getSingularLabel()) { 27 | $singularLabel = str_singular($this->config()->getLabel()); 28 | } 29 | 30 | if ($translated) { 31 | return __($singularLabel); 32 | } 33 | 34 | return $singularLabel; 35 | } 36 | 37 | public function getEntryLabelTemplate() 38 | { 39 | return $this->config()->getEntryLabel(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Domains/Resource/Resource/ResourceActivityEvent.php: -------------------------------------------------------------------------------- 1 | request = $request; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Resource/TestHelper.php: -------------------------------------------------------------------------------- 1 | resource = $resource; 17 | } 18 | 19 | public function asOptions($placeholder = null) 20 | { 21 | $options = $this->resource->newQuery()->get()->map(function($entry) { 22 | return ['value' => $entry->getId(), 'text' => $this->resource->getEntryLabel($entry)]; 23 | })->all(); 24 | 25 | return $options; 26 | } 27 | } -------------------------------------------------------------------------------- /src/Domains/Resource/ResourceDriver.php: -------------------------------------------------------------------------------- 1 | hydrate($attributes); 19 | } 20 | 21 | public function getParam($key) 22 | { 23 | return array_get($this->params, $key); 24 | } 25 | 26 | public function setParam($key, $value): ResourceDriver 27 | { 28 | $this->params[$key] = $value; 29 | 30 | return $this; 31 | } 32 | 33 | public function getType() 34 | { 35 | return $this->type; 36 | } 37 | 38 | /** 39 | * Get the instance as an array. 40 | * 41 | * @return array 42 | */ 43 | public function toArray() 44 | { 45 | return [ 46 | 'type' => $this->type, 47 | 'params' => $this->params, 48 | ]; 49 | } 50 | 51 | public function toDsn() 52 | { 53 | return sprintf("%s@%s://%s", $this->getType(), $this->getParam('connection'), $this->getParam('table')); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Domains/Resource/Table/Contracts/AltersTableQuery.php: -------------------------------------------------------------------------------- 1 | visibility = $visibility; 17 | } 18 | 19 | public function scopeIs($scope) 20 | { 21 | $this->wheres[] = ['op' => 'and', 'key' => 'scope', 'value' => $scope]; 22 | 23 | return $this; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/Resource/Visibility/Visibility.php: -------------------------------------------------------------------------------- 1 | hide[] = $condition = new Condition($this); 12 | 13 | return $condition; 14 | } 15 | } -------------------------------------------------------------------------------- /src/Domains/TaskManager/Contracts/Task.php: -------------------------------------------------------------------------------- 1 | task = $task; 21 | } 22 | 23 | public function handle(Deployer $deployer) 24 | { 25 | $deployer->deploy($this->task); 26 | } 27 | 28 | public function getTask(): Task 29 | { 30 | return $this->task; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Domains/TaskManager/Deployer.php: -------------------------------------------------------------------------------- 1 | setStatus(TaskStatus::processing()); 13 | 14 | $handler = $task->getHandler(); 15 | 16 | try { 17 | $handler->handle($task->getPayload()); 18 | 19 | $task->setStatus(TaskStatus::success()); 20 | } catch (Exception $e) { 21 | $task->setStatus(TaskStatus::error()); 22 | $task->setInfo($e->getMessage()); 23 | } 24 | } 25 | 26 | public static function resolve() 27 | { 28 | return app(static::class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Domains/TaskManager/TaskStatus.php: -------------------------------------------------------------------------------- 1 | equals(static::pending()); 17 | } 18 | 19 | public function isError(): bool 20 | { 21 | return $this->equals(static::error()); 22 | } 23 | 24 | public function isSuccess(): bool 25 | { 26 | return $this->equals(static::success()); 27 | } 28 | 29 | public function isProcessing(): bool 30 | { 31 | return $this->equals(static::processing()); 32 | } 33 | 34 | public static function pending(): self 35 | { 36 | return new static(self::PENDING); 37 | } 38 | 39 | public static function error(): self 40 | { 41 | return new static(self::ERROR); 42 | } 43 | 44 | public static function success(): self 45 | { 46 | return new static(self::SUCCESS); 47 | } 48 | 49 | public static function processing(): self 50 | { 51 | return new static(self::PROCESSING); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Domains/UI/Components/ActionComponent.php: -------------------------------------------------------------------------------- 1 | props->merge($this->action->compose()->get()); 18 | } 19 | 20 | public function uuid() 21 | { 22 | return $this->action->uuid(); 23 | } 24 | 25 | public static function from(Action $action): self 26 | { 27 | $static = new static; 28 | $static->action = $action; 29 | 30 | return $static; 31 | } 32 | } -------------------------------------------------------------------------------- /src/Domains/UI/Components/Button.php: -------------------------------------------------------------------------------- 1 | name; 12 | } 13 | 14 | /** 15 | * Create an HTTP response that represents the object. 16 | * 17 | * @param \Illuminate\Http\Request $request 18 | * @return \Illuminate\Http\Response 19 | */ 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/Domains/UI/Components/ComponentContract.php: -------------------------------------------------------------------------------- 1 | addClass("mr-{$value}"); 20 | } 21 | 22 | /** 23 | * Set width 24 | * 25 | * @param $value 26 | * @return static 27 | */ 28 | public function w($value): self 29 | { 30 | return $this->addClass("w-{$value}"); 31 | } 32 | 33 | /** 34 | * Set padding 35 | * 36 | * @param $value 37 | * @return self 38 | */ 39 | public function p($value): self 40 | { 41 | return $this->addClass("p-{$value}"); 42 | } 43 | 44 | public function card(): self 45 | { 46 | return $this->addClass('sv-card'); 47 | } 48 | } -------------------------------------------------------------------------------- /src/Domains/UI/Components/FormComponent.php: -------------------------------------------------------------------------------- 1 | props->merge($this->form->compose()->get()); 17 | } 18 | 19 | public function uuid() 20 | { 21 | return $this->form->getIdentifier(); 22 | } 23 | 24 | public static function from(Form $form): self 25 | { 26 | $static = new static; 27 | $static->form = $form; 28 | 29 | return $static; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Domains/UI/Components/Html.php: -------------------------------------------------------------------------------- 1 | name; 12 | } 13 | } -------------------------------------------------------------------------------- /src/Domains/UI/Components/ImageComponent.php: -------------------------------------------------------------------------------- 1 | name; 12 | } 13 | } -------------------------------------------------------------------------------- /src/Domains/UI/Components/Layout/RowComponent.php: -------------------------------------------------------------------------------- 1 | name; 15 | } 16 | 17 | public function addColumn(ComponentContract $column): self 18 | { 19 | $this->props->push($column, 'columns'); 20 | 21 | return $this; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Domains/UI/Components/PageComponent.php: -------------------------------------------------------------------------------- 1 | name; 17 | } 18 | 19 | public function uuid() 20 | { 21 | return $this->uuid; 22 | } 23 | 24 | public function onComposed(Payload $payload) 25 | { 26 | $payload->set('class', ['w-full']); 27 | } 28 | 29 | public static function from(Page $page): self 30 | { 31 | $static = new static; 32 | $static->uuid = $page->uuid(); 33 | $static->props->merge([ 34 | 'meta' => $page->getMeta(), 35 | 'actions' => $page->getActions(), 36 | 'sections' => $page->getSections(), 37 | 'blocks' => $page->getBlocks(), 38 | ]); 39 | 40 | return $static; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Domains/UI/Components/TableComponent.php: -------------------------------------------------------------------------------- 1 | name; 17 | } 18 | 19 | public function uuid() 20 | { 21 | return $this->table->getConfig()->uuid(); 22 | } 23 | 24 | public static function from(Table $table): self 25 | { 26 | $static = new static; 27 | $static->table = $table; 28 | $static->props->merge($table->getConfig()->compose()->get()); 29 | // $static->card(); 30 | 31 | return $static; 32 | } 33 | } -------------------------------------------------------------------------------- /src/Domains/UI/Http/Controllers/WakeupController.php: -------------------------------------------------------------------------------- 1 | $object->compose()]; 17 | } else { 18 | throw PlatformException::fail('Object is not composable'); 19 | } 20 | } 21 | } 22 | 23 | return null; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Domains/UI/Nucleo/BarChart.php: -------------------------------------------------------------------------------- 1 | props['rows'][] = $block; 13 | } 14 | 15 | return $this; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Domains/UI/Nucleo/SvTab.php: -------------------------------------------------------------------------------- 1 | title = $title; 17 | 18 | return $this; 19 | } 20 | 21 | public function content(SvComponent $content) 22 | { 23 | $this->content = $content; 24 | return $this; 25 | } 26 | 27 | public function setGuardKey($guardKey) 28 | { 29 | $this->content->setGuardKey($guardKey); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * @return mixed 36 | */ 37 | public function getTitle() 38 | { 39 | return $this->title; 40 | } 41 | 42 | /** 43 | * @return mixed 44 | */ 45 | public function getContent() 46 | { 47 | return $this->content; 48 | } 49 | 50 | public function autoFetch() 51 | { 52 | $this->fetch = true; 53 | 54 | return $this; 55 | } 56 | 57 | /** 58 | * @return bool 59 | */ 60 | public function isAutoFetch() 61 | { 62 | return $this->fetch; 63 | } 64 | } -------------------------------------------------------------------------------- /src/Events/BaseEvent.php: -------------------------------------------------------------------------------- 1 | guard()->attempt($credentials, true)) { 12 | return response()->json(['status' => 'error', 'error' => ['description' => 'Invalid credentials']], 401); 13 | } 14 | 15 | return response()->json([ 16 | 'status' => 'ok', 17 | 'data' => [ 18 | 'access_token' => $token, 19 | 'token_type' => 'bearer', 20 | 'expires_in' => $this->guard()->factory()->getTTL() * 60, 21 | ], 22 | ]); 23 | } 24 | 25 | protected function guard() 26 | { 27 | return auth()->guard('sv-api'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Http/Controllers/BaseApiController.php: -------------------------------------------------------------------------------- 1 | middleware('sv.auth:sv-api'); 14 | $this->middleware(WatchActivity::class); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Http/Controllers/BaseController.php: -------------------------------------------------------------------------------- 1 | request = app('request'); 26 | $this->events = app('events'); 27 | $this->route = $this->request->route(); 28 | } 29 | 30 | public static function at($method) 31 | { 32 | return get_called_class().'@'.$method; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Http/Middleware/AutoLoginDev.php: -------------------------------------------------------------------------------- 1 | shouldLoginAutomatically($request)) { 20 | if ($userId = app(Users::class)->withEmail($this->getUser($request))->id) { 21 | auth()->onceUsingId($userId); 22 | } 23 | } 24 | 25 | return $next($request); 26 | } 27 | 28 | /** 29 | * @param \Illuminate\Http\Request $request 30 | * @return mixed 31 | */ 32 | protected function getUser($request) 33 | { 34 | return $request->get('user', env('SV_TEST_USER', 'root@superv.io')); 35 | } 36 | 37 | protected function shouldLoginAutomatically(Request $request) 38 | { 39 | return Current::envIsLocal() 40 | && ! $request->hasHeader('authorization') 41 | && ! $request->has('token') 42 | && Current::port()->guard() === 'sv-api'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Http/Middleware/PlatformAuthenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 19 | return redirect()->to('/'); 20 | } 21 | } 22 | 23 | public function guard($request, $guard) 24 | { 25 | if ($this->auth->guard($guard)->check()) { 26 | return $this->auth->shouldUse($guard); 27 | } 28 | 29 | throw new AuthenticationException( 30 | 'Unauthenticated.', [$guard], $this->redirectTo($request) 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Http/Middleware/SetLocale.php: -------------------------------------------------------------------------------- 1 | has('locale')) { 19 | $selectedLocale = $request->get('locale'); 20 | $request->session()->put('locale', $selectedLocale); 21 | 22 | app()->setLocale($selectedLocale); 23 | 24 | return redirect()->to($request->getPathInfo()); 25 | } elseif (session()->has('locale')) { 26 | $selectedLocale = session('locale'); 27 | app()->setLocale($selectedLocale); 28 | } 29 | 30 | return $next($request); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Listeners/PortDetectedListener.php: -------------------------------------------------------------------------------- 1 | port); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Listeners/RouteMatchedListener.php: -------------------------------------------------------------------------------- 1 | detector = $detector; 17 | } 18 | 19 | public function handle($event) 20 | { 21 | $this->detector->detect($event->request); 22 | } 23 | } -------------------------------------------------------------------------------- /src/Resources/Auth/ActionsList.php: -------------------------------------------------------------------------------- 1 | makeSelectable(); 16 | 17 | $table->addSelectionAction(DeleteActionsAction::make('platform.auth_actions.actions:bulk')); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Resources/Auth/DeleteActionsAction.php: -------------------------------------------------------------------------------- 1 | count(); 17 | 18 | $query->get()->map(function ($item) { 19 | $item->delete(); 20 | }); 21 | 22 | return ['data' => ['message' => sprintf("%s items were deleted", $count)]]; 23 | } 24 | } -------------------------------------------------------------------------------- /src/Resources/FieldsList.php: -------------------------------------------------------------------------------- 1 | get('name')->searchable(); 16 | $fields->get('resource')->copyToFilters(); 17 | $fields->get('type')->copyToFilters(); 18 | 19 | $table->setOption('limit', 50); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Resources/FormsList.php: -------------------------------------------------------------------------------- 1 | get('identifier')->searchable(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Resources/FormsResource.php: -------------------------------------------------------------------------------- 1 | label('Form Entries'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Resources/MediaList.php: -------------------------------------------------------------------------------- 1 | hideLabel(); 18 | 19 | $fields->showFirst('owner')->copyToFilters(); 20 | 21 | $fields->add(['type' => 'file', 'name' => 'image', 'identifier' => 'image']) 22 | ->setCallback('table.composing', function (Payload $payload, EntryContract $entry) { 23 | $payload->set('image_url', url('storage/'.$entry->filename)); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Resources/ResourceActivityDashboardPage.php: -------------------------------------------------------------------------------- 1 | notCreatable(); 15 | 16 | // $fields = $resource->indexFields(); 17 | // $fields->show('entry'); 18 | // $fields->show('user')->copyToFilters(); 19 | // $fields->show('resource')->copyToFilters(); 20 | // 21 | // $resource->searchable(['email']); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Resources/ResourcesList.php: -------------------------------------------------------------------------------- 1 | showIdColumn(); 16 | $table->setOption('limit', 10); 17 | 18 | $fields->get('identifier')->searchable(); 19 | $fields->get('namespace')->showOnIndex()->copyToFilters(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Resources/TasksList.php: -------------------------------------------------------------------------------- 1 | show('status'); 16 | $fields->show('created_at'); 17 | 18 | $table->orderByLatest(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Resources/Users/UsersEntryDashboardPage.php: -------------------------------------------------------------------------------- 1 | addAction('update_password'); 16 | $page->addAction('impersonate'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Resources/Users/UsersForm.php: -------------------------------------------------------------------------------- 1 | fields()->hide('remember_token'); 16 | $form->fields()->hide('deleted_at'); 17 | $form->fields()->hide('deleted_by'); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Resources/Users/UsersList.php: -------------------------------------------------------------------------------- 1 | show('name')->searchable(); 16 | $fields->show('email')->searchable(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Resources/Users/UsersResource.php: -------------------------------------------------------------------------------- 1 | registerAction('update_password', UpdatePasswordAction::class); 15 | $resource->registerAction('impersonate', ImpersonateAction::class); 16 | 17 | $resource->getField('password')->addFlag('view.hide'); 18 | $resource->getField('remember_token')->addFlag('view.hide'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Support/Composer/Composable.php: -------------------------------------------------------------------------------- 1 | tokens = wrap_array($tokens); 13 | } 14 | 15 | public function merge(array $tokens): self 16 | { 17 | $this->tokens = array_merge($this->tokens, $tokens); 18 | 19 | return $this; 20 | } 21 | 22 | public function get() 23 | { 24 | return $this->tokens; 25 | } 26 | } -------------------------------------------------------------------------------- /src/Support/Concerns/HasOptions.php: -------------------------------------------------------------------------------- 1 | options; 18 | } 19 | 20 | public function setOptions(Collection $options) 21 | { 22 | $this->options = $options; 23 | 24 | return $this; 25 | } 26 | 27 | /** 28 | * @param $key 29 | * @param $value 30 | * @return $this 31 | */ 32 | public function setOption($key, $value) 33 | { 34 | $this->options->put($key, $value); 35 | 36 | return $this; 37 | } 38 | 39 | /** 40 | * @param $key 41 | * @param null $default 42 | * @return mixed 43 | */ 44 | public function getOption($key, $default = null) 45 | { 46 | return $this->options->get($key, $default); 47 | } 48 | } -------------------------------------------------------------------------------- /src/Support/Concerns/HasPath.php: -------------------------------------------------------------------------------- 1 | path), '/'); 10 | } 11 | 12 | protected function realPath() 13 | { 14 | return starts_with($this->path, '/') ? $this->path : base_path($this->path); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Support/Concerns/Hydratable.php: -------------------------------------------------------------------------------- 1 | hydratables)) { 16 | $parameters = array_intersect_key($parameters, array_flip($this->hydratables)); 17 | } 18 | 19 | foreach ($parameters as $parameter => $value) { 20 | if (is_null($value)) { 21 | continue; 22 | } 23 | 24 | if (!$overrideDefault && !is_null($this->$parameter)) 25 | continue; 26 | 27 | if (method_exists($this, $method = camel_case('set_'.$parameter))) { 28 | $this->{$method}($value); 29 | } elseif (property_exists($this, $parameter)) { 30 | $this->$parameter = $value; 31 | } elseif (property_exists($this, $camelCaseParameter = camel_case($parameter))) { 32 | $this->$camelCaseParameter = $value; 33 | } 34 | } 35 | 36 | return $this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Support/Dispatchable.php: -------------------------------------------------------------------------------- 1 | dispatch(new static(...func_get_args())); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Support/Fireable.php: -------------------------------------------------------------------------------- 1 | $value) { 10 | $method = camel_case('set_'.$parameter); 11 | 12 | if (method_exists($object, $method)) { 13 | $object->{$method}($value); 14 | } 15 | } 16 | 17 | return $object; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Support/Path.php: -------------------------------------------------------------------------------- 1 | name; 21 | } 22 | 23 | public function uuid() 24 | { 25 | return $this->uuid; 26 | } 27 | 28 | public function countProp($key) 29 | { 30 | if ($prop = $this->getProp($key)) { 31 | return count($prop); 32 | } 33 | 34 | return 0; 35 | } 36 | 37 | public static function fromArray($array) 38 | { 39 | $component = new static($array['props']); 40 | $component->name = $array['component']; 41 | $component->uuid = $array['uuid'] ?? null; 42 | 43 | return $component; 44 | } 45 | 46 | public static function fromUrl($url) 47 | { 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | testing --------------------------------------------------------------------------------