├── .editorconfig ├── .eslintignore ├── .eslintrc.yml ├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .npmignore ├── .vscode └── launch.json ├── LICENSE ├── README.md ├── applications ├── .gitkeep └── readme.md ├── backend ├── error.js └── respond.js ├── bin ├── acl.js ├── adduser.js ├── bg.js ├── cluster ├── export.js ├── import-data.js ├── import.js ├── job-runner.js ├── job.js ├── schedule.js ├── setup.js └── www ├── config ├── config.json ├── config.json.devel ├── config.json.prod ├── index.js └── setup.ini.example ├── core ├── CollectionFieldModes.js ├── ConditionParser.js ├── ConditionTypes.js ├── DataSourceFunctionCodes.js ├── DateSizes.js ├── DateTypes.js ├── FieldModes.js ├── FieldSizes.js ├── FieldTypes.js ├── FunctionCodes.js ├── IonError.js ├── OperationTypes.js ├── Permissions.js ├── PropertyTypes.js ├── RuntimeEvents.js ├── SortingModes.js ├── SortingParser.js ├── User.js ├── UserTypes.js ├── buffer.js ├── cast.js ├── datasources.js ├── di.js ├── empty.js ├── equal.js ├── error-setup.js ├── errors │ ├── auth.js │ ├── conditions.js │ ├── data-repo.js │ ├── data-source.js │ ├── file-storage.js │ ├── front-end.js │ ├── meta-repo.js │ ├── validation.js │ └── workflow.js ├── extend.js ├── extendModuleDi.js ├── i18n.js ├── impl │ ├── Background.js │ ├── Calculator │ │ ├── func │ │ │ ├── aggreg │ │ │ │ ├── avg.js │ │ │ │ ├── count.js │ │ │ │ ├── index.js │ │ │ │ ├── max.js │ │ │ │ ├── merge.js │ │ │ │ ├── min.js │ │ │ │ ├── oper.js │ │ │ │ ├── processed.js │ │ │ │ ├── skipper.js │ │ │ │ └── sum.js │ │ │ ├── arithmetic │ │ │ │ ├── add.js │ │ │ │ ├── decOper.js │ │ │ │ ├── div.js │ │ │ │ ├── incOper.js │ │ │ │ ├── mul.js │ │ │ │ ├── round.js │ │ │ │ └── sub.js │ │ │ ├── arrays │ │ │ │ ├── element.js │ │ │ │ └── in.js │ │ │ ├── bool │ │ │ │ ├── and.js │ │ │ │ ├── not.js │ │ │ │ └── or.js │ │ │ ├── cmp │ │ │ │ ├── cmpOper.js │ │ │ │ ├── empty.js │ │ │ │ ├── eq.js │ │ │ │ ├── gt.js │ │ │ │ ├── gte.js │ │ │ │ ├── lt.js │ │ │ │ ├── lte.js │ │ │ │ ├── ne.js │ │ │ │ └── nempty.js │ │ │ ├── condition │ │ │ │ └── if.js │ │ │ ├── data │ │ │ │ ├── contains.js │ │ │ │ ├── get.js │ │ │ │ ├── index.js │ │ │ │ └── size.js │ │ │ ├── date │ │ │ │ ├── date.js │ │ │ │ ├── dateAdd.js │ │ │ │ ├── dateDiff.js │ │ │ │ ├── dateFormat.js │ │ │ │ └── now.js │ │ │ ├── index.js │ │ │ ├── obj.js │ │ │ ├── parser.js │ │ │ ├── process │ │ │ │ └── collect.js │ │ │ ├── produce │ │ │ │ └── number2words.js │ │ │ ├── sequence │ │ │ │ ├── index.js │ │ │ │ └── next.js │ │ │ ├── string │ │ │ │ ├── concat.js │ │ │ │ ├── like.js │ │ │ │ ├── lower.js │ │ │ │ ├── pad.js │ │ │ │ ├── substr.js │ │ │ │ └── upper.js │ │ │ └── util.js │ │ └── index.js │ ├── DigitalSignManager.js │ ├── EventManager.js │ ├── LocalAccountStorage.js │ ├── QueryParser │ │ ├── classes.js │ │ ├── grammar │ │ │ ├── grammar.ne │ │ │ └── index.js │ │ ├── index.js │ │ └── test │ │ │ └── grammar.spec.js │ ├── Scheduler.js │ ├── SchedulerAgent.js │ ├── WorkflowProvider.js │ ├── access │ │ ├── DsAcl.js │ │ ├── DsRoleAccessChangeLogger.js │ │ ├── DsRoleAccessManager.js │ │ ├── aclMetaMap.js │ │ ├── aclmongo.js │ │ └── amAccessManager.js │ ├── cache │ │ ├── CacheProxy.js │ │ ├── DsCacheRepository.js │ │ ├── InnerCacheRepository.js │ │ ├── memcached │ │ │ └── MemcachedRepository.js │ │ └── redis │ │ │ └── RedisRepository.js │ ├── changelogger │ │ ├── DsChangeLogger.js │ │ ├── DsChangelogFactory.js │ │ └── EventLogger.js │ ├── datarepository │ │ ├── CachedDataRepository.js │ │ ├── SecuredDataRepository.js │ │ └── ionDataRepository.js │ ├── datasource │ │ ├── MongoSequenceProvider.js │ │ └── mongodb.js │ ├── email │ │ ├── NodeMailer.js │ │ └── SendMail.js │ ├── log │ │ ├── IonLogger.js │ │ ├── LogRecorder.js │ │ └── LoggerProxy.js │ ├── meta │ │ ├── DsMetaRepository.js │ │ ├── keyProvider.js │ │ └── mongo │ │ │ └── dbSync.js │ ├── notifications │ │ ├── EmailNotifier.js │ │ └── Notifier.js │ ├── resource │ │ ├── FsStorage.js │ │ ├── ImageStorage.js │ │ └── OwnCloudStorage │ │ │ ├── OwnCloudError.js │ │ │ ├── SharesApi.js │ │ │ ├── index.js │ │ │ └── util.js │ └── settings │ │ ├── DsSettingsRepository.js │ │ ├── Settings.js │ │ ├── SettingsRepository.js │ │ └── util │ │ └── merge-configs.js ├── interfaces │ ├── AccountStorage.js │ ├── AclProvider.js │ ├── Calculator.js │ ├── ChangeLogger.js │ ├── DataRepository │ │ ├── DataRepository.js │ │ ├── index.js │ │ └── lib │ │ │ ├── Item.js │ │ │ ├── Property.js │ │ │ └── util.js │ ├── DataSource.js │ ├── DbSync.js │ ├── DigitalSignManager.js │ ├── EmailSender.js │ ├── InsertPreprocessor.js │ ├── Iterator.js │ ├── KeyProvider.js │ ├── ListPreprocessor.js │ ├── Logger.js │ ├── MetaRepository │ │ ├── MetaRepository.js │ │ ├── index.js │ │ └── lib │ │ │ └── ClassMeta.js │ ├── NotificationSender.js │ ├── Notifier.js │ ├── Preprocessor.js │ ├── QueryParser.js │ ├── Repository.js │ ├── ResourceStorage │ │ ├── index.js │ │ └── lib │ │ │ ├── Share.js │ │ │ ├── ShareAccessLevel.js │ │ │ ├── StoredFile.js │ │ │ └── ThumbnailGenerator.js │ ├── RoleAccessManager.js │ ├── SequenceProvider.js │ ├── SettingsRepository.js │ └── WorkflowProvider.js ├── period.js ├── readAppDeployConfig.js ├── resolvePath.js ├── scope-alias.js ├── strToDate.js ├── strings.js ├── system.js └── util │ ├── chain.js │ ├── dateOffset.js │ ├── dirName.js │ ├── formula.js │ ├── normalize.js │ ├── number2words.js │ ├── read.js │ ├── recacher.js │ ├── request.js │ └── schedule.js ├── dispatcher ├── controllers │ └── api │ │ ├── i18n.js │ │ ├── markAllAsViewed.js │ │ ├── markAsViewed.js │ │ ├── moreViewedNotifications.js │ │ └── notifications.js └── index.js ├── docs ├── en │ ├── 1_system_deployment │ │ ├── step1_installing_environment.md │ │ ├── step2_project_with_modules.md │ │ └── step3_building_and_running.md │ ├── 2_system_description │ │ ├── functionality │ │ │ ├── cached.md │ │ │ ├── eds.md │ │ │ ├── filter.md │ │ │ ├── functionality.md │ │ │ ├── module_templates.md │ │ │ ├── namespace.md │ │ │ ├── notifications.md │ │ │ ├── printed_forms.md │ │ │ ├── schedule.md │ │ │ ├── utilities.md │ │ │ └── virtual_attr.md │ │ ├── metadata_structure │ │ │ ├── correspondance_table.md │ │ │ ├── meta_class │ │ │ │ ├── abstract.md │ │ │ │ ├── ancestor.md │ │ │ │ ├── atr_autoassigned.md │ │ │ │ ├── atr_cached_true.md │ │ │ │ ├── atr_default_value.md │ │ │ │ ├── atr_formula.md │ │ │ │ ├── atr_indexed.md │ │ │ │ ├── atr_itemclass_backcoll.md │ │ │ │ ├── atr_ref_backref.md │ │ │ │ ├── atr_selconditions.md │ │ │ │ ├── atr_selectionprovider.md │ │ │ │ ├── atr_selsorting.md │ │ │ │ ├── binding.md │ │ │ │ ├── composite_indexes.md │ │ │ │ ├── eager_loading.md │ │ │ │ ├── isstruct.md │ │ │ │ ├── journaling.md │ │ │ │ ├── key.md │ │ │ │ ├── meta_class_attribute.md │ │ │ │ ├── meta_class_main.md │ │ │ │ ├── metaversion.md │ │ │ │ ├── property_types.md │ │ │ │ ├── semantic.md │ │ │ │ ├── time_user_tracker.md │ │ │ │ ├── type_collection14.md │ │ │ │ ├── type_datetime9.md │ │ │ │ ├── type_geodata100.md │ │ │ │ ├── type_isstruct16.md │ │ │ │ ├── type_reference13.md │ │ │ │ ├── type_schedule210.md │ │ │ │ └── type_user17.md │ │ │ ├── meta_navigation │ │ │ │ ├── conditions.md │ │ │ │ ├── meta_navigation.md │ │ │ │ ├── navigation_nodes.md │ │ │ │ ├── navigation_section.md │ │ │ │ └── title.md │ │ │ ├── meta_report │ │ │ │ ├── example.md │ │ │ │ └── meta_report.md │ │ │ ├── meta_scheme.md │ │ │ ├── meta_security │ │ │ │ └── meta_security.md │ │ │ ├── meta_variables.md │ │ │ ├── meta_view │ │ │ │ ├── allowsearch.md │ │ │ │ ├── commands.md │ │ │ │ ├── comments.md │ │ │ │ ├── create_edit_view.md │ │ │ │ ├── enablement.md │ │ │ │ ├── field_sizes.md │ │ │ │ ├── fields.md │ │ │ │ ├── fileshare.md │ │ │ │ ├── list_view.md │ │ │ │ ├── mask.md │ │ │ │ ├── meta_view_attribute.md │ │ │ │ ├── meta_view_main.md │ │ │ │ ├── obligation.md │ │ │ │ ├── options.md │ │ │ │ ├── overridemode.md │ │ │ │ ├── styles.md │ │ │ │ ├── tabs.md │ │ │ │ ├── tags.md │ │ │ │ ├── type_coll_ref.md │ │ │ │ ├── type_group.md │ │ │ │ ├── view_types.md │ │ │ │ └── visibility.md │ │ │ └── meta_workflows │ │ │ │ ├── meta_workflows.md │ │ │ │ ├── security_wf.md │ │ │ │ ├── status_wf.md │ │ │ │ └── transitions_wf.md │ │ └── platform_configuration │ │ │ ├── auth.md │ │ │ ├── deploy.md │ │ │ ├── deploy_ex.md │ │ │ ├── deploy_globals.md │ │ │ ├── deploy_modules.md │ │ │ ├── ini_files.md │ │ │ └── package.md │ ├── 3_modules_description │ │ ├── account.md │ │ ├── admin.md │ │ ├── admin_security.md │ │ ├── dashboards.md │ │ ├── gantt_chart.md │ │ ├── modules.md │ │ ├── portal.md │ │ ├── registry.md │ │ ├── registry_code.md │ │ ├── registry_treegrid.md │ │ ├── report.md │ │ ├── report_warning.md │ │ └── soap.md │ ├── images │ │ ├── ION_logo_black_mini.png │ │ ├── Insta.png │ │ ├── facebook.png │ │ ├── iondv_logo.png │ │ ├── linkedin.png │ │ ├── schema_en.png │ │ └── twitter.png │ ├── index.md │ └── key_features.md └── ru │ ├── 1_system_deployment │ ├── files_in_folder_bin.md │ ├── step1_installing_environment.md │ ├── step2_project_with_modules.md │ └── step3_building_and_running.md │ ├── 2_system_description │ ├── functionality │ │ ├── cached.md │ │ ├── eds.md │ │ ├── filter.md │ │ ├── functionality.md │ │ ├── module_templates.md │ │ ├── namespace.md │ │ ├── notifications.md │ │ ├── printed_forms.md │ │ ├── schedule.md │ │ ├── utilities.md │ │ └── virtual_attr.md │ ├── metadata_structure │ │ ├── correspondance_table.md │ │ ├── meta_class │ │ │ ├── abstract.md │ │ │ ├── ancestor.md │ │ │ ├── atr_autoassigned.md │ │ │ ├── atr_cached_true.md │ │ │ ├── atr_default_value.md │ │ │ ├── atr_formula.md │ │ │ ├── atr_indexed.md │ │ │ ├── atr_itemclass_backcoll.md │ │ │ ├── atr_ref_backref.md │ │ │ ├── atr_selconditions.md │ │ │ ├── atr_selectionprovider.md │ │ │ ├── atr_selsorting.md │ │ │ ├── binding.md │ │ │ ├── composite_indexes.md │ │ │ ├── eager_loading.md │ │ │ ├── isstruct.md │ │ │ ├── journaling.md │ │ │ ├── key.md │ │ │ ├── meta_class_attribute.md │ │ │ ├── meta_class_main.md │ │ │ ├── metaversion.md │ │ │ ├── property_types.md │ │ │ ├── semantic.md │ │ │ ├── time_user_tracker.md │ │ │ ├── type_collection14.md │ │ │ ├── type_datetime9.md │ │ │ ├── type_geodata100.md │ │ │ ├── type_isstruct16.md │ │ │ ├── type_reference13.md │ │ │ ├── type_schedule210.md │ │ │ └── type_user17.md │ │ ├── meta_navigation │ │ │ ├── conditions.md │ │ │ ├── meta_navigation.md │ │ │ ├── navigation_nodes.md │ │ │ ├── navigation_section.md │ │ │ └── title.md │ │ ├── meta_report │ │ │ ├── example.md │ │ │ └── meta_report.md │ │ ├── meta_scheme.md │ │ ├── meta_security │ │ │ └── meta_security.md │ │ ├── meta_variables.md │ │ ├── meta_view │ │ │ ├── allowsearch.md │ │ │ ├── commands.md │ │ │ ├── comments.md │ │ │ ├── create_edit_view.md │ │ │ ├── enablement.md │ │ │ ├── field_sizes.md │ │ │ ├── fields.md │ │ │ ├── fileshare.md │ │ │ ├── list_view.md │ │ │ ├── mask.md │ │ │ ├── meta_view_attribute.md │ │ │ ├── meta_view_main.md │ │ │ ├── obligation.md │ │ │ ├── options.md │ │ │ ├── overridemode.md │ │ │ ├── styles.md │ │ │ ├── tabs.md │ │ │ ├── tags.md │ │ │ ├── type_coll_ref.md │ │ │ ├── type_group.md │ │ │ ├── view_types.md │ │ │ └── visibility.md │ │ └── meta_workflows │ │ │ ├── meta_workflows.md │ │ │ ├── security_wf.md │ │ │ ├── status_wf.md │ │ │ └── transitions_wf.md │ └── platform_configuration │ │ ├── auth.md │ │ ├── deploy.md │ │ ├── deploy_ex.md │ │ ├── deploy_globals.md │ │ ├── deploy_modules.md │ │ ├── ini_files.md │ │ └── package.md │ ├── 3_modules_description │ ├── account.md │ ├── admin.md │ ├── admin_security.md │ ├── dashboards.md │ ├── gantt_chart.md │ ├── modules.md │ ├── portal.md │ ├── registry.md │ ├── registry_code.md │ ├── registry_treegrid.md │ ├── report.md │ ├── report_warning.md │ └── soap.md │ ├── 4_ion_model │ └── ion_environment.md │ ├── 7_develop │ ├── app-utils │ │ ├── button.md │ │ ├── job.md │ │ ├── print-form.md │ │ ├── readme.md │ │ ├── rest.md │ │ └── workflow.md │ ├── core │ │ └── dataRepo.md │ └── fieldTemplate.md │ ├── images │ ├── ION_logo_black_mini.png │ ├── Insta.png │ ├── app_structure1.png │ ├── facebook.png │ ├── iondv_logo.png │ ├── iondv_readme1.png │ ├── linkedin.png │ ├── schema.png │ ├── sel_provider.jpg │ └── twitter.png │ ├── index.md │ ├── key_features.md │ └── readme.md ├── gulpfile.js ├── i18n ├── .keep └── ru │ └── framework.po ├── lib ├── aclImport.js ├── appSetup.js ├── auth.js ├── config-reader.js ├── deploy.js ├── duration.js ├── export.js ├── import-data.js ├── import-meta.js ├── interfaces │ ├── ProfilePlugin.js │ └── StrategyProvider.js ├── last-visit.js ├── oAuthAdapter.js ├── plugins │ ├── EventNotifier.js │ ├── bulkNotifier.js │ └── customProfile.js ├── server.js ├── session │ ├── connect-adapter.js │ ├── dsStore.js │ └── index.js ├── util │ ├── crossNav.js │ ├── extViews.js │ ├── recache.js │ ├── staticRouter.js │ ├── storageDirectoryParser.js │ ├── sysMenuCheck.js │ ├── theme.js │ └── viewResolver.js └── wsAuth.js ├── modules └── readme.md ├── package.json ├── strings ├── errors │ ├── auth.js │ ├── conditions.js │ ├── data-repo.js │ ├── data-source.js │ ├── di.js │ ├── file-storage.js │ ├── front-end.js │ ├── index.js │ ├── meta-repo.js │ ├── validation.js │ └── workflow.js ├── frontend.js └── templates-default.js ├── test ├── .eslintrc.yml ├── lib │ └── get-meta.js ├── quality │ ├── files-format.spec.js │ └── meta-class-link.spec.js └── readme.md └── view ├── .eslintrc.yml └── default ├── static ├── css │ ├── auth.css │ └── base.css ├── favicon.ico ├── fonts │ ├── FontAwesome.otf │ ├── et-line.eot │ ├── et-line.svg │ ├── et-line.ttf │ ├── et-line.woff │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ ├── fontawesome-webfont.woff2 │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── img │ ├── ico-lock.png │ └── ico-user.png └── package.json └── templates ├── 403.ejs ├── changePwd.ejs ├── login.ejs ├── oauth-grant.ejs ├── profile.ejs └── register.ejs /.editorconfig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/.editorconfig -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # /node_modules/* and /bower_components/* ignored by default 2 | **/node_modules/** 3 | # **/view/** 4 | **/vendor/** 5 | **/*.min.js 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | 3 | /.hg/* 4 | /.idea/* 5 | /.git/* 6 | /.settings/* 7 | /.tmp/* 8 | /.project 9 | /distr/* 10 | /docker/* 11 | /**/node_modules/* 12 | /plugins/* 13 | /modules/* 14 | !/modules/readme.md 15 | /applications/* 16 | 17 | /htmlFiles 18 | 19 | /view/**/node_modules/* 20 | /view/**/*.less.css 21 | /view/**/*.min.css 22 | /view/**/*.min.js 23 | 24 | /files 25 | /log/* 26 | 27 | /config/*.ini 28 | 29 | /npm-debug.log 30 | *.swp 31 | 32 | /.git-*/* 33 | output.log 34 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | *.iws 4 | *.log 5 | .project 6 | .DS_Store 7 | .sass-cache 8 | .idea 9 | node_modules/ 10 | bower_components/ 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "skipFiles": [ 12 | "/**" 13 | ], 14 | "program": "${workspaceFolder}/bin/www", 15 | "env":{ 16 | "NODE_PATH": "${workspaceFolder}/framework" 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /applications/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/applications/.gitkeep -------------------------------------------------------------------------------- /applications/readme.md: -------------------------------------------------------------------------------- 1 | # Folder assignment 2 | The folder is intended for placing IONDV applications. 3 | -------------------------------------------------------------------------------- /backend/error.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 07.09.16. 3 | */ 4 | 'use strict'; 5 | 6 | const Logger = require('core/interfaces/Logger'); 7 | 8 | /** 9 | * @param {{}} scope 10 | * @param {Logger} [scope.sysLog] 11 | * @param {Error | String} err 12 | * @param {Response} res 13 | * @param {String | Boolean} userMsg 14 | */ 15 | module.exports = function (scope, err, res, userMsg) { 16 | if (scope.logRecorder) { 17 | scope.logRecorder.stop(); 18 | } 19 | 20 | if (scope && scope.sysLog && scope.sysLog instanceof Logger) { 21 | scope.sysLog.error(err); 22 | } else { 23 | console.error(err); 24 | } 25 | 26 | let msg; 27 | if (typeof userMsg === 'boolean' && userMsg) { 28 | msg = 'Internal server error.'; 29 | } else { 30 | msg = userMsg || (err instanceof Error ? err.getMessage(res.locals.lang) : err); 31 | } 32 | 33 | if (res) { 34 | res.status(500).send(msg); 35 | } 36 | return false; 37 | }; 38 | -------------------------------------------------------------------------------- /backend/respond.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 09.09.16. 3 | */ 4 | 'use strict'; 5 | 6 | const di = require('core/di'); 7 | const onError = require('./error'); 8 | 9 | module.exports = function (required, worker, res) { 10 | var scope = di.context('app'); 11 | if (!scope) { 12 | return onError(scope, new Error('app DI-container not found'), res, true); 13 | } 14 | 15 | if (Array.isArray(required)) { 16 | for (var i = 0; i < required.length; i++) { 17 | if (typeof scope[required[i]] === 'undefined' || !scope[required[i]]) { 18 | return onError(scope, new Error('Required component not set up ' + required[i]), res, true); 19 | } 20 | } 21 | } 22 | 23 | worker(scope); 24 | }; 25 | -------------------------------------------------------------------------------- /bin/import.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* eslint no-process-exit:off, no-sync:off */ 3 | /** 4 | * Created by kras on 10.07.16. 5 | */ 6 | const metaImporter = require('lib/import-meta'); 7 | const config = require('../config'); 8 | const di = require('core/di'); 9 | const IonLogger = require('core/impl/log/IonLogger'); 10 | const errorSetup = require('core/error-setup'); 11 | const alias = require('core/scope-alias'); 12 | const path = require('path'); 13 | const extend = require('extend'); 14 | const {t, lang, load} = require('core/i18n'); 15 | lang(config.lang); 16 | errorSetup(); 17 | 18 | var sysLog = new IonLogger(config.log || {}); 19 | 20 | var params = { 21 | src: '../in', 22 | ns: null 23 | }; 24 | 25 | let setParam = null; 26 | 27 | process.argv.forEach(function (val) { 28 | if (val.substr(0, 2) === '--') { 29 | setParam = val.substr(2); 30 | } else if (setParam) { 31 | params[setParam] = val; 32 | } 33 | }); 34 | 35 | load(path.normalize(path.join(__dirname, '..', 'i18n')), null, config.lang) 36 | .then(() => di('boot', config.bootstrap, {sysLog: sysLog}, null, ['rtEvents'])) 37 | .then(scope => 38 | di( 39 | 'app', 40 | di.extract( 41 | ['dbSync', 'metaRepo', 'dataRepo', 'workflows', 'sequenceProvider'], 42 | extend(true, config.di, scope.settings.get('plugins') || {}) 43 | ), 44 | {}, 45 | 'boot', 46 | ['auth', 'application'] 47 | ) 48 | ) 49 | .then(scope => alias(scope, scope.settings.get('di-alias'))) 50 | .then(scope => 51 | metaImporter(params.src, 52 | { 53 | sync: scope.dbSync, 54 | metaRepo: scope.metaRepo, 55 | log: sysLog, 56 | namespace: params.ns 57 | }).then(() => scope) 58 | ) 59 | .then(scope => scope.dataSources.disconnect()) 60 | .then(() => { 61 | console.info(t('Model import successfully done')); 62 | process.exit(0); 63 | }) 64 | .catch((err) => { 65 | console.error(err); 66 | process.exit(130); 67 | }); 68 | -------------------------------------------------------------------------------- /bin/schedule.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* eslint no-process-exit:off */ 3 | /** 4 | * Created by krasilneg on 19.07.17. 5 | */ 6 | const config = require('../config'); 7 | const di = require('core/di'); 8 | const extend = require('extend'); 9 | const IonLogger = require('core/impl/log/IonLogger'); 10 | const sysLog = new IonLogger(config.log || {}); 11 | const errorSetup = require('core/error-setup'); 12 | const path = require('path'); 13 | const {t, load, lang} = require('core/i18n'); 14 | lang(config.lang); 15 | errorSetup(); 16 | 17 | 18 | // jshint maxcomplexity: 20, maxstatements: 30 19 | load(path.normalize(path.join(__dirname, '..', 'i18n')), null, config.lang) 20 | .then(() => di('boot', config.bootstrap, {sysLog: sysLog}, null, ['rtEvents'])) 21 | .then(scope => 22 | di( 23 | 'app', 24 | di.extract('scheduler', extend(true, config.di, scope.settings.get('plugins') || {})), 25 | {}, 26 | 'boot' 27 | ) 28 | ) 29 | .then( 30 | /** 31 | * @param {{}} scope 32 | * @param {SettingsRepository} [scope.settings] 33 | * @returns {Promise} 34 | */ 35 | (scope) => { 36 | return scope.scheduler.start(); 37 | } 38 | ) 39 | .then(() => { 40 | sysLog.info(t('Schedule started')); 41 | }) 42 | .catch((err) => { 43 | sysLog.error(err); 44 | process.exit(130); 45 | }); -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* eslint no-process-exit:off, no-sync:off */ 3 | 'use strict'; 4 | const config = require('../config'); 5 | const IonLogger = require('core/impl/log/IonLogger'); 6 | const sysLog = new IonLogger(config.log || {}); 7 | const server = require('lib/server'); 8 | const {t} = require('core/i18n'); 9 | 10 | server({ 11 | config, 12 | sysLog, 13 | onStart: (scope) => { 14 | if (config.runJobs) { 15 | sysLog.info(t('Starting scheduler')); 16 | return scope.scheduler.start().then(() => { 17 | sysLog.info(t('Scheduler started')); 18 | }); 19 | } 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /config/config.json.devel: -------------------------------------------------------------------------------- 1 | { 2 | "log_level": "notice", 3 | "port": [ 4 | 3000, 5 | 3001, 6 | 3002 7 | ], 8 | "defaultModule":"registry", 9 | "datasources":[ 10 | { 11 | "name":"Db", 12 | "module":"core/impl/datasource/mongodb", 13 | "config": { 14 | "uri": "mongodb://127.0.0.1:27017/database", 15 | "options": { 16 | "server": { 17 | "socketOptions":{ 18 | "keepAlive": 1 19 | } 20 | } 21 | }, 22 | "connectionLimit": 10, 23 | "schema": "database", 24 | "user": "user", 25 | "password": "pwd" 26 | } 27 | } 28 | ], 29 | "metaDs": "Db", 30 | "dataDs": "Db", 31 | "sessionDs": "Db", 32 | "auth": { 33 | "denyTopLevel": false, 34 | "localAuthDS": "Db" 35 | }, 36 | "policy": [ 37 | { 38 | "module": "core/impl/access/aclmongo", 39 | "config": { 40 | "accessDs": "Db" 41 | } 42 | } 43 | ], 44 | "session": { 45 | "secret": "ion:demo:secret", 46 | "resave": false, 47 | "saveUninitialized": true 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /config/config.json.prod: -------------------------------------------------------------------------------- 1 | { 2 | "log_level": "error", 3 | "port": [ 4 | 8888, 5 | 8889 6 | ], 7 | "defaultModule":"registry", 8 | "datasources":[ 9 | { 10 | "name":"Db", 11 | "module":"core/impl/datasource/mongodb", 12 | "config": { 13 | "uri": "mongodb://127.0.0.1:27017/database", 14 | "options": { 15 | "server": { 16 | "socketOptions":{ 17 | "keepAlive": 1 18 | } 19 | } 20 | }, 21 | "connectionLimit": 10, 22 | "schema": "database", 23 | "user": "user", 24 | "password": "pwd" 25 | } 26 | } 27 | ], 28 | "metaDs": "Db", 29 | "dataDs": "Db", 30 | "sessionDs": "Db", 31 | "auth": { 32 | "denyTopLevel": false, 33 | "localAuthDS": "Db" 34 | }, 35 | "policy": [ 36 | { 37 | "module": "core/impl/access/aclmongo", 38 | "config": { 39 | "accessDs": "Db" 40 | } 41 | } 42 | ], 43 | "session": { 44 | "secret": "ion:demo:secret", 45 | "resave": false, 46 | "saveUninitialized": true 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let path = require('path'); 4 | let read = require('lib/config-reader'); 5 | let {readConfig} = require('core/util/read'); 6 | let config = readConfig(path.join(__dirname, './config.json')); 7 | 8 | module.exports = read(config, __dirname); 9 | 10 | -------------------------------------------------------------------------------- /config/setup.ini.example: -------------------------------------------------------------------------------- 1 | #deploy.mode=db 2 | 3 | db.uri=mongodb://127.0.0.1:27017/db 4 | #db.authSource=admin 5 | #db.authMechanism=SCRAM-SHA-1 6 | #db.hosts=127.0.0.1:27017 7 | #db.dbname=db 8 | #db.user=username 9 | #db.pwd=password 10 | 11 | server.ports[]=8888 12 | server.ports[]=8889 13 | 14 | module.default=registry 15 | module.skip[]=offline-sync 16 | 17 | fs.storageRoot=./files 18 | fs.urlBase=/files 19 | 20 | #server.requestSizeLimit=100mb 21 | 22 | auth.denyTop=false 23 | auth.registration=false 24 | #auth.aclProvider=aclProvider 25 | 26 | # Exclusion from security checks 27 | auth.exclude[]=/files/** 28 | auth.exclude[]=/images/** 29 | 30 | auth.exclude[]=/ 31 | auth.exclude[]=/vendor/** 32 | auth.exclude[]=/css/** 33 | auth.exclude[]=/fonts/** 34 | auth.exclude[]=/favicon.ico 35 | 36 | auth.exclude[]=/registry/vendor/** 37 | auth.exclude[]=/registry/css/** 38 | auth.exclude[]=/registry/js/** 39 | auth.exclude[]=/registry/app-vendor/** 40 | auth.exclude[]=/registry/app-static/** 41 | auth.exclude[]=/registry/common-static/** 42 | auth.exclude[]=/registry/img/** 43 | auth.exclude[]=/registry/fonts/** 44 | auth.exclude[]=/dashboard/vendor/** 45 | auth.exclude[]=/dashboard/js/** 46 | auth.exclude[]=/gantt-chart/vendor/** 47 | auth.exclude[]=/gantt-chart/gantt/** 48 | auth.exclude[]=/gantt-chart/css/** 49 | auth.exclude[]=/gantt-chart/js/** 50 | auth.exclude[]=/gantt-chart/common-static/** 51 | auth.exclude[]=/gantt-chart/fonts/** 52 | auth.exclude[]=/geomap/vendor/** 53 | auth.exclude[]=/geomap/css/** 54 | auth.exclude[]=/geomap/js/** 55 | auth.exclude[]=/geomap/common-static/** 56 | auth.exclude[]=/geomap/img/** 57 | auth.exclude[]=/geomap/fonts/** 58 | auth.exclude[]=/report/vendor/** 59 | auth.exclude[]=/report/css/** 60 | auth.exclude[]=/report/js/** 61 | auth.exclude[]=/report/common-static/** 62 | auth.exclude[]=/report/img/** 63 | auth.exclude[]=/report/fonts/** 64 | 65 | auth.exclude[]=/portal/** 66 | -------------------------------------------------------------------------------- /core/CollectionFieldModes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (email: inkz@xakep.ru, telegram: @inkz1) on 08.07.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | LIST: 0, 8 | LINK: 1, 9 | LINKS: 2, 10 | TABLE: 3 11 | }; 12 | -------------------------------------------------------------------------------- /core/ConditionTypes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 31.08.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | EQUAL: 0, 8 | NOT_EQUAL: 1, 9 | EMPTY: 2, 10 | NOT_EMPTY: 3, 11 | LIKE: 4, 12 | LESS: 5, 13 | MORE: 6, 14 | LESS_OR_EQUAL: 7, 15 | MORE_OR_EQUAL: 8, 16 | IN: 9, 17 | CONTAINS: 10 18 | }; 19 | -------------------------------------------------------------------------------- /core/DataSourceFunctionCodes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 14.04.17. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | JOIN_EXISTS: 'joinExists', 8 | JOIN_NOT_EXISTS: 'joinNotExists', 9 | JOIN_SIZE: 'joinSize' 10 | }; 11 | -------------------------------------------------------------------------------- /core/DateSizes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 28.04.19. 3 | */ 4 | module.exports = { 5 | MILLISECONDS: 0, 6 | SECONDS: 1, 7 | MINUTES: 2, 8 | HOURS: 3, 9 | DAY: 4 10 | }; -------------------------------------------------------------------------------- /core/DateTypes.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | REAL: 0, 3 | LOCALIZED: 1, 4 | UTC: 2 5 | }; -------------------------------------------------------------------------------- /core/FieldModes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 04.09.16. 3 | */ 4 | 'use strict'; 5 | module.exports = { 6 | TEXT_SIMPLE: 0, 7 | TEXT_AUTOCOMPLETE: 1, 8 | 9 | COLLECTION_LIST: 0, 10 | COLLECTION_LINK: 1, 11 | COLLECTION_LINKS: 2, 12 | COLLECTION_TABLE: 3, 13 | COLLECTION_HASHTAGS: 4, 14 | 15 | REF_STRING: 0, 16 | REF_LINK: 1, 17 | REF_INFO: 2, 18 | REF_HIERARCHY: 3, 19 | REF_SPECIFY: 4, 20 | 21 | GEO_MAP: 0, 22 | GEO_LOCATOR: 1, 23 | GEO_CANVAS: 2, 24 | 25 | GROUP_VERTICAL: 0, 26 | GROUP_HORIZONTAL: 1 27 | }; 28 | -------------------------------------------------------------------------------- /core/FieldSizes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 26.06.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | TINY: 0, 8 | SHORT: 1, 9 | MEDIUM: 2, 10 | LONG: 3, 11 | BIG: 4 12 | }; 13 | -------------------------------------------------------------------------------- /core/FieldTypes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 26.06.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | GROUP: 0, 8 | TEXT: 1, 9 | REFERENCE: 2, 10 | COLLECTION: 3, 11 | CHECKBOX: 4, 12 | COMBO: 5, 13 | DATE_PICKER: 120, 14 | DATETIME_PICKER: 6, 15 | MULTILINE: 7, 16 | WYSIWYG: 8, 17 | RADIO: 9, 18 | MULTISELECT: 10, 19 | FILE: 11, 20 | PASSWORD: 12, 21 | IMAGE: 13, 22 | NUMBER_PICKER: 14, 23 | DECIMAL_EDITOR: 15, 24 | URL: 17, 25 | PERIOD_PICKER: 60, 26 | GEO: 100, 27 | ATTACHMENTS: 110, 28 | SCHEDULE: 210, 29 | CALENDAR: 220 30 | }; 31 | -------------------------------------------------------------------------------- /core/FunctionCodes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | EQUAL: 'eq', 5 | NOT_EQUAL: 'ne', 6 | EMPTY: 'empty', 7 | NOT_EMPTY: 'nempty', 8 | CONTAINS: 'contains', 9 | LIKE: 'like', 10 | LESS: 'lt', 11 | GREATER: 'gt', 12 | LESS_OR_EQUAL: 'lte', 13 | GREATER_OR_EQUAL: 'gte', 14 | IN: 'in', 15 | AND: 'and', 16 | OR: 'or', 17 | NOT: 'not', 18 | DATE: 'date', 19 | NOW: 'now', 20 | DATE_ADD: 'dateAdd', 21 | DATE_DIFF: 'dateDiff', 22 | DATE_FORMAT: 'dateFormat', 23 | DATE_YEAR: 'year', 24 | DATE_MONTH: 'month', 25 | DATE_DAY: 'day', 26 | DATE_HOUR: 'hour', 27 | DATE_MINUTE: 'minute', 28 | DATE_SECOND: 'second', 29 | ADD: 'add', 30 | SUB: 'sub', 31 | MUL: 'mul', 32 | DIV: 'div', 33 | ROUND: 'round', 34 | CONCAT: 'concat', 35 | SUBSTR: 'substr', 36 | MOD: 'mod', 37 | ABS: 'abs', 38 | MIN: 'min', 39 | MAX: 'max', 40 | AVG: 'avg', 41 | SUM: 'sum', 42 | COUNT: 'count', 43 | FULL_TEXT_MATCH: 'match', 44 | GEO_WITHIN: 'geoWithin', 45 | GEO_INTERSECTS: 'geoIntersects', 46 | IF: 'if', 47 | CASE: 'case', 48 | IFNULL: 'ifNull', 49 | LITERAL: 'literal', 50 | SIZE: 'size', 51 | FORMAT: 'format', 52 | NUMBER_TO_WORDS: 'number2words', 53 | TO_UPPER: 'upper', 54 | TO_LOWER: 'lower' 55 | }; 56 | -------------------------------------------------------------------------------- /core/IonError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 2/27/17. 3 | */ 4 | const strings = require('core/strings'); 5 | 6 | /** 7 | * 8 | * @param {String | Number} code 9 | * @param {{}} [params] 10 | * @param {Error} cause 11 | * @constructor 12 | */ 13 | function IonError(code, params, cause) { 14 | 15 | this.code = code; 16 | 17 | this.cause = cause; 18 | 19 | this.params = params || {}; 20 | 21 | Object.defineProperty(this, 'message', { 22 | get: () => strings.s('errors', code, params) || cause && cause.message || 'Unknown error' 23 | }); 24 | 25 | Error.captureStackTrace(this, IonError); 26 | } 27 | 28 | IonError.prototype = Object.create(Error.prototype); 29 | IonError.prototype.constructor = IonError; 30 | IonError.prototype.getMessage = function (lang) { 31 | return strings.s('errors', this.code, this.params, lang) || this.cause && this.cause.message || 'Unknown error'; 32 | }; 33 | 34 | module.exports = IonError; 35 | 36 | /** 37 | * @param {{}} base 38 | */ 39 | module.exports.registerMessages = function (base) { 40 | if (base) { 41 | strings.registerBase('errors', base); 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /core/OperationTypes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 31.08.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | AND: 0, 8 | OR: 1, 9 | NOT: 2, 10 | MIN: 3, 11 | MAX: 4, 12 | AVG: 5, 13 | SUM: 6, 14 | COUNT: 7, 15 | DATE: 8, 16 | DATEADD: 9, 17 | DATEDIFF: 10, 18 | ADD: 11, 19 | SUB: 12, 20 | MUL: 13, 21 | DIV: 14, 22 | MOD: 15, 23 | ROUND: 16, 24 | CONCAT: 17, 25 | SUBSTR: 18, 26 | ABS: 19, 27 | DATE_STR: 20, 28 | DATE_YEAR: 21, 29 | DATE_MONTH: 23, 30 | DATE_DAY: 24, 31 | DATE_HOUR: 25, 32 | DATE_MINUTE: 26, 33 | DATE_SECOND: 27 34 | }; 35 | -------------------------------------------------------------------------------- /core/Permissions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 25.10.16. 3 | */ 4 | 'use strict'; 5 | // jshint maxcomplexity: 15, bitwise: false 6 | 7 | function addVal(result, val) { 8 | if (Array.isArray(result)) { 9 | result.push(val); 10 | } else { 11 | result[val] = true; 12 | } 13 | } 14 | 15 | const Permissions = { 16 | READ: 'read', // 1 17 | WRITE: 'write', // 2 18 | DELETE: 'delete', // 4 19 | USE: 'use', // 8 20 | FULL: 'full', // 31 21 | 22 | ATTR_CONTENT_CREATE: 'c_create', 23 | ATTR_CONTENT_EDIT: 'c_edit', 24 | ATTR_CONTENT_VIEW: 'c_view', 25 | ATTR_CONTENT_DELETE: 'c_delete', 26 | 27 | /** 28 | * @param {Number} mask 29 | * @param {Boolean} [asArray] 30 | */ 31 | fromBitMask: function (mask, asArray) { 32 | var result = asArray ? [] : {}; 33 | 34 | if ((1 & mask) === 1) { 35 | addVal(result, Permissions.READ); 36 | } 37 | if ((mask & 2) === 2) { 38 | addVal(result, Permissions.WRITE); 39 | } 40 | if ((mask & 4) === 4) { 41 | addVal(result, Permissions.DELETE); 42 | } 43 | if ((mask & 8) === 8) { 44 | addVal(result, Permissions.USE); 45 | } 46 | if ((mask & 31) === 31) { 47 | addVal(result, Permissions.FULL); 48 | } 49 | return result; 50 | } 51 | }; 52 | 53 | module.exports = Permissions; 54 | -------------------------------------------------------------------------------- /core/PropertyTypes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (email: inkz@xakep.ru, telegram: @inkz1) on 03.05.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | STRING: 0, 8 | TEXT: 1, 9 | HTML: 2, 10 | URL: 3, 11 | IMAGE: 4, 12 | FILE: 5, 13 | INT: 6, 14 | REAL: 7, 15 | DECIMAL: 8, 16 | DATETIME: 9, 17 | BOOLEAN: 10, 18 | PASSWORD: 11, 19 | GUID: 12, 20 | REFERENCE: 13, 21 | COLLECTION: 14, 22 | SET: 15, 23 | STRUCT: 16, 24 | CUSTOM: 17, 25 | USER: 18, 26 | PERIOD: 60, 27 | GEO: 100, 28 | FILE_LIST: 110, 29 | SCHEDULE: 210 30 | }; 31 | -------------------------------------------------------------------------------- /core/RuntimeEvents.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 19.07.16. 3 | */ 4 | 'use strict'; 5 | var EventEmitter = require('events').EventEmitter; 6 | var util = require('util'); 7 | 8 | function RuntimeEvents(options) { 9 | var _this = this; 10 | 11 | if (options.target instanceof EventEmitter) { 12 | if (options.startEvent) { 13 | options.target.on(options.startEvent, function () { 14 | _this.emit('started'); 15 | }); 16 | } 17 | if (options.stopEvent) { 18 | options.target.on(options.stopEvent, function () { 19 | _this.emit('stopped'); 20 | }); 21 | } 22 | } 23 | } 24 | 25 | util.inherits(RuntimeEvents, EventEmitter); 26 | module.exports = RuntimeEvents; 27 | 28 | -------------------------------------------------------------------------------- /core/SortingModes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 13.10.2016. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | ASC: 0, 8 | DESC: 1 9 | }; 10 | -------------------------------------------------------------------------------- /core/SortingParser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 2/25/17. 3 | */ 4 | const SortingModes = require('core/SortingModes'); 5 | 6 | module.exports = function sortParser(sorting) { 7 | if (!sorting) { 8 | return {}; 9 | } 10 | let sort = typeof sorting === 'string' ? JSON.parse(sorting) : sorting; 11 | let result = {}; 12 | for (let i = 0; i < sort.length; i++) { 13 | result[sort[i].property] = parseInt(sort[i].mode) === SortingModes.DESC ? -1 : 1; 14 | } 15 | return result; 16 | }; 17 | -------------------------------------------------------------------------------- /core/User.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 07.06.17. 3 | */ 4 | 5 | function User(data, coactors, tz) { 6 | let ca = coactors || {}; 7 | 8 | let timezone = tz; 9 | 10 | this.id = function() { 11 | return data.id + (data.type ? `@${data.type}` : ''); 12 | }; 13 | 14 | this.login = function () { 15 | return data.id; 16 | }; 17 | 18 | this.name = function () { 19 | return data.name || this.id(); 20 | }; 21 | 22 | this.type = function() { 23 | return data.type; 24 | }; 25 | 26 | this.email = function() { 27 | return (data.properties && data.properties.email) || data.email; 28 | }; 29 | 30 | this.pwdDate = function() { 31 | return data.pwdDate; 32 | }; 33 | 34 | this.pwdHash = function() { 35 | return data.pwd; 36 | }; 37 | 38 | this.needPwdReset = function() { 39 | return data.needPwdReset; 40 | }; 41 | 42 | this.toString = function() { 43 | return this.name(); 44 | }; 45 | 46 | this.properties = function() { 47 | return data.properties || {}; 48 | }; 49 | 50 | this.setTz = function(tz) { 51 | timezone = tz; 52 | }; 53 | 54 | this.setCoactors = function(ca2) { 55 | ca = Object.assign(ca, ca2); 56 | }; 57 | 58 | this.setProperties = function(properties) { 59 | data.properties = Object.assign(data.properties || {}, properties); 60 | }; 61 | 62 | this.isMe = function(sid) { 63 | return this.id() === sid || ca.hasOwnProperty(sid) && ca[sid]; 64 | }; 65 | 66 | this.addCoactor = function(id) { 67 | ca[id] = true; 68 | }; 69 | 70 | this.coactors = function() { 71 | return Object.keys(ca); 72 | }; 73 | 74 | this.timeZone = function() { 75 | return timezone; 76 | }; 77 | 78 | this.isDisabled = function() { 79 | return data.disabled; 80 | }; 81 | 82 | this.language = function() { 83 | return data.language; 84 | }; 85 | } 86 | 87 | module.exports = User; 88 | -------------------------------------------------------------------------------- /core/UserTypes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 29.07.17. 3 | */ 4 | module.exports = { 5 | LOCAL: 'local', 6 | SYSTEM: 'system' 7 | }; 8 | -------------------------------------------------------------------------------- /core/buffer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 08.10.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = function (data, enc) { 7 | if (process.version.substring(1, 1) === '6') { 8 | return Buffer.from(data, enc); 9 | } 10 | return new Buffer(data, enc); 11 | }; 12 | -------------------------------------------------------------------------------- /core/cast.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 04.09.16. 3 | */ 4 | 'use strict'; 5 | 6 | const PropertyTypes = require('./PropertyTypes'); 7 | // jshint maxcomplexity: 30 8 | module.exports = function cast(value, type) { 9 | if (value === null || typeof value === 'undefined') { 10 | return value; 11 | } 12 | 13 | if (Array.isArray(value)) { 14 | var result = []; 15 | for (var i = 0; i < value.length; i++) { 16 | result.push(cast(value[i], type)); 17 | } 18 | return result; 19 | } 20 | 21 | if ( 22 | type === PropertyTypes.STRING || 23 | type === PropertyTypes.TEXT || 24 | type === PropertyTypes.HTML || 25 | type === PropertyTypes.URL 26 | ) { 27 | return value.toString(); 28 | } 29 | 30 | switch (type){ 31 | case PropertyTypes.BOOLEAN: 32 | if (value === 'false') { 33 | return false; 34 | } 35 | return Boolean(value); 36 | case PropertyTypes.DATETIME: 37 | return value ? (value instanceof Date ? value : new Date(value)) : null; 38 | case PropertyTypes.REAL: 39 | case PropertyTypes.DECIMAL: 40 | value = parseFloat(value); 41 | return isNaN(value) ? null : value; 42 | case PropertyTypes.SET: 43 | case PropertyTypes.INT: 44 | value = parseInt(value); 45 | return isNaN(value) ? null : value; 46 | default: 47 | return value; 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /core/datasources.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 24.02.16. 3 | */ 4 | 'use strict'; 5 | 6 | const LoggerProxy = require('core/impl/log/LoggerProxy'); 7 | const {t} = require('core/i18n'); 8 | 9 | function Datasources(options) { 10 | var _this = this; 11 | /** 12 | * @type {DataSource[]} 13 | */ 14 | this.sources = options.sources; 15 | 16 | /** 17 | * @type {RuntimeEvents} 18 | */ 19 | this.runtimeEvents = options.runtimeEvents; 20 | 21 | var log = options.logger || new LoggerProxy(); 22 | 23 | /** 24 | * @returns {Promise} 25 | */ 26 | this.connect = function () { 27 | var all, i; 28 | all = []; 29 | log.info(t('Connecting datasources')); 30 | for (i = 0; i < this.sources.length; i++) { 31 | all.push(this.sources[i].open()); 32 | } 33 | return Promise.all(all); 34 | }; 35 | 36 | /** 37 | * @returns {Promise} 38 | */ 39 | this.disconnect = function () { 40 | var all, i; 41 | all = []; 42 | for (i = 0; i < this.sources.length; i++) { 43 | all.push(this.sources[i].close()); 44 | } 45 | return Promise.all(all); 46 | }; 47 | 48 | if (this.runtimeEvents) { 49 | this.runtimeEvents.on('stop', function () { 50 | _this.disconnect().then(function () { 51 | log.info(t('All datasources successfully disconnected!')); 52 | }).catch(function (err) { 53 | log.error(err); 54 | }); 55 | }); 56 | } 57 | } 58 | 59 | module.exports = Datasources; 60 | -------------------------------------------------------------------------------- /core/empty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 07.12.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = function (obj) { 7 | if (obj) { 8 | for (var nm in obj) { 9 | if (obj.hasOwnProperty(nm)) { 10 | return false; 11 | } 12 | } 13 | } 14 | return true; 15 | }; 16 | -------------------------------------------------------------------------------- /core/equal.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 04.09.16. 3 | */ 4 | // jshint eqeqeq: false 5 | module.exports = function (checkedValue, metaValue) { 6 | if (checkedValue instanceof Date) { 7 | return checkedValue == metaValue || 8 | checkedValue.getTime() == metaValue || 9 | checkedValue.toString() == metaValue || 10 | checkedValue.toDateString() === metaValue || 11 | checkedValue.toJSON() === metaValue || 12 | checkedValue.toISOString() === metaValue; 13 | } 14 | if (typeof checkedValue === 'boolean') { 15 | return checkedValue ? metaValue && metaValue != 'false' : metaValue == 'false' || !metaValue; 16 | } 17 | return checkedValue == metaValue; 18 | }; 19 | -------------------------------------------------------------------------------- /core/error-setup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 5 | const IonError = require('core/IonError'); 6 | const path = require('path'); 7 | const fs = require('fs'); 8 | const {t} = require('core/i18n'); 9 | const {format} = require('util'); 10 | 11 | /** 12 | * @param {String} baseDir 13 | */ 14 | module.exports = function errorSetup(baseDir) { 15 | baseDir = baseDir || path.normalize(path.join(__dirname, '..', 'strings')); 16 | const msgDir = path.join(baseDir, 'errors'); 17 | if (!fs.existsSync(msgDir)) // eslint-disable-line no-sync 18 | throw new Error(format(t('Error message base does not exist in path "%s"'), baseDir)); 19 | IonError.registerMessages(require(msgDir)); 20 | }; 21 | -------------------------------------------------------------------------------- /core/errors/auth.js: -------------------------------------------------------------------------------- 1 | const PREFIX = 'auth'; 2 | 3 | module.exports = { 4 | NO_DS: `${PREFIX}.nods`, 5 | FORBID: `${PREFIX}.forbid`, 6 | TMP_BLOCK: `${PREFIX}.tmpb`, 7 | FAIL: `${PREFIX}.fail`, 8 | LACK_PWD: `${PREFIX}.lackpwd`, 9 | UNAVAILABLE: `${PREFIX}.unavail`, 10 | NO_PWD: `${PREFIX}.nopwd`, 11 | INTERNAL_ERR: `${PREFIX}.500`, 12 | BAD_PWD_REPEAT: `${PREFIX}.bpwdr`, 13 | MIN_PWD_LENGTH: `${PREFIX}.mpwdl`, 14 | PRIOR_PWD: `${PREFIX}.priorpwd`, 15 | WEAK_PWD: `${PREFIX}.weakpwd`, 16 | UPPER_LOWER: `${PREFIX}.uplower`, 17 | NUMBERS: `${PREFIX}.numbers`, 18 | SPECIAL: `${PREFIX}.special`, 19 | AND: `${PREFIX}.and`, 20 | REG_BAN: `${PREFIX}.regban`, 21 | REG_FAIL: `${PREFIX}.regfail`, 22 | EDIT_USER_FAIL: `${PREFIX}.euf`, 23 | PWD_BAN_NOT_FINISHED: `${PREFIX}.pbnf`, 24 | NOT_AUTHENTICATED: `${PREFIX}.notauthent`, 25 | USER_BAN: `${PREFIX}.usrban`, 26 | BAD_USER_ID: `${PREFIX}.badid`, 27 | EXT_AUTH_FAIL: `${PREFIX}.extauthfail`, 28 | NO_STRATEGY: `${PREFIX}.nostrategy` 29 | }; 30 | -------------------------------------------------------------------------------- /core/errors/conditions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const PREFIX = 'conditions'; 3 | 4 | module.exports = { 5 | NON_APPLICABLE: `${PREFIX}.non_applicable`, 6 | ATTR_NOT_FOUND: `${PREFIX}.attr_not_found`, 7 | INVALID_AGGREG: `${PREFIX}.invalid_aggreg`, 8 | INVALID_CONDITION: `${PREFIX}.invalid_cond`, 9 | INVALID_OPERATION: `${PREFIX}.invalid_oper`, 10 | NO_ARGS: `${PREFIX}.no_args`, 11 | }; -------------------------------------------------------------------------------- /core/errors/data-repo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const PREFIX = 'data-repo'; 6 | 7 | module.exports = { 8 | ITEM_EXISTS: `${PREFIX}.exists`, 9 | ITEM_EXISTS_MULTI: `${PREFIX}.iem`, 10 | ITEM_NOT_FOUND: `${PREFIX}.inf`, 11 | EXISTS_IN_COL: `${PREFIX}.eic`, 12 | BAD_PARAMS: `${PREFIX}.bp`, 13 | FILE_ATTR_SAVE: `${PREFIX}.fas`, 14 | FILE_ATTR_LOAD: `${PREFIX}.fal`, 15 | NO_COLLECTION: `${PREFIX}.nocol`, 16 | INVALID_META: `${PREFIX}.im`, 17 | COMPOSITE_KEY: `${PREFIX}.ck`, 18 | CONTAINER_NOT_FOUND: `${PREFIX}.cnf`, 19 | FAIL: `${PREFIX}.fail`, 20 | MISSING_REQUIRED: `${PREFIX}.mr`, 21 | NO_KEY_SPEC: `${PREFIX}.nkv`, 22 | NO_BACK_REF: `${PREFIX}.nbr`, 23 | UNEXPECTED_ASYNC: `${PREFIX}.ueasync`, 24 | PERMISSION_LACK: `${PREFIX}.noperm` 25 | }; 26 | -------------------------------------------------------------------------------- /core/errors/data-source.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const PREFIX = 'data-source'; 6 | 7 | module.exports = { 8 | UNIQUENESS_VIOLATION: `${PREFIX}.uv`, 9 | BAD_QUERY: `${PREFIX}.bq`, 10 | OPER_FAILED: `${PREFIX}.of` 11 | }; 12 | -------------------------------------------------------------------------------- /core/errors/file-storage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const PREFIX = 'file-storage'; 6 | 7 | module.exports = { 8 | BAD_DATA: `${PREFIX}.bd`, 9 | NO_DIR: `${PREFIX}.nd`, 10 | NO_FILE: `${PREFIX}.nf` 11 | }; 12 | -------------------------------------------------------------------------------- /core/errors/front-end.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 08.05.17. 3 | */ 4 | 'use strict'; 5 | const PREFIX = 'front-end'; 6 | 7 | module.exports = { 8 | ACCESS_DENIED: `${PREFIX}.403` 9 | }; 10 | -------------------------------------------------------------------------------- /core/errors/meta-repo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const PREFIX = 'meta-repo'; 6 | 7 | module.exports = { 8 | NO_CLASS: `${PREFIX}.nc`, 9 | NO_ATTR: `${PREFIX}.na`, 10 | NO_VIEW: `${PREFIX}.nv`, 11 | NO_WORKFLOW: `${PREFIX}.nw` 12 | }; 13 | -------------------------------------------------------------------------------- /core/errors/validation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const PREFIX = 'validation'; 3 | 4 | module.exports = { 5 | INCORRECT_VALUE: { 6 | INT: `${PREFIX}.iv.int`, 7 | REAL: `${PREFIX}.iv.rl`, 8 | DECIMAL: `${PREFIX}.iv.dcml`, 9 | DATETIME: `${PREFIX}.iv.dt`, 10 | PERIOD: `${PREFIX}.iv.prd`, 11 | DEFAULT: `${PREFIX}.iv.def` 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /core/errors/workflow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const PREFIX = 'workflow'; 6 | 7 | module.exports = { 8 | WORKFLOW_NOT_FOUND: `${PREFIX}.wnf`, 9 | TRANS_ERROR: `${PREFIX}.te`, 10 | STATE_NOT_FOUND: `${PREFIX}.snf`, 11 | CONDITION_VIOLATION: `${PREFIX}.cv`, 12 | NOT_IN_WORKFLOW: `${PREFIX}.nw`, 13 | TRANS_IMPOSSIBLE: `${PREFIX}.ti`, 14 | TRANS_NOT_FOUND: `${PREFIX}.tnf`, 15 | IN_WORKFLOW: `${PREFIX}.iw`, 16 | ACCESS_DENIED: `${PREFIX}.iw` 17 | }; 18 | -------------------------------------------------------------------------------- /core/extend.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const clone = require('clone'); 3 | 4 | module.exports = function extend() { 5 | let target = arguments[0]; 6 | let i = 1; 7 | let length = arguments.length; 8 | let cln; 9 | if (typeof target !== 'object') { 10 | cln = !!target; 11 | if (length < 2) { 12 | throw new Error('Invalid parameters count'); 13 | } 14 | target = cln ? clone(arguments[1]) : arguments[1]; 15 | i = 2; 16 | } 17 | target = target || {}; 18 | for (; i < arguments.length; i++) { 19 | if (arguments[i] && typeof arguments[i] === 'object') { 20 | let src = arguments[i]; 21 | for (let nm in src) { 22 | if (src.hasOwnProperty(nm)) { 23 | let v = src[nm]; 24 | if (Array.isArray(v)) { 25 | if (Array.isArray(target[nm])) { 26 | if (cln) { 27 | target[nm] = target[nm].concat(v); 28 | } else { 29 | target[nm].push(...v); 30 | } 31 | } else { 32 | target[nm] = v; 33 | } 34 | } else if (v && typeof v === 'object') { 35 | if (target[nm] && typeof target[nm] === 'object') { 36 | target[nm] = extend(cln, target[nm], v); 37 | } else { 38 | target[nm] = v; 39 | } 40 | } else { 41 | target[nm] = v; 42 | } 43 | } 44 | } 45 | } 46 | } 47 | return target; 48 | }; 49 | -------------------------------------------------------------------------------- /core/extendModuleDi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 29.09.16. 3 | */ 4 | 'use strict'; 5 | const di = require('./di'); 6 | const extend = require('core/extend'); 7 | 8 | /** 9 | * @param {String} moduleName 10 | * @param {{}} config 11 | * @param {{}} [rootScope] 12 | * @returns {*} 13 | */ 14 | module.exports = function (moduleName, config, rootScope) { 15 | if (!rootScope) { 16 | /** 17 | * @type {{settings: SettingsRepository}} 18 | */ 19 | rootScope = di.context('app'); 20 | } 21 | 22 | if (rootScope.settings) { 23 | let extDi = rootScope.settings.get(`${moduleName}.di`); 24 | if (extDi) { 25 | return extend(true, config, extDi); 26 | } 27 | } 28 | return config; 29 | }; 30 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/avg.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./oper'); 6 | const skipper = require('./skipper'); 7 | const Item = require('core/interfaces/DataRepository').Item; 8 | 9 | /** 10 | * @param {DataRepository} dataRepo 11 | * @returns {Function} 12 | */ 13 | module.exports = c( 14 | (col, attr, cond) => { 15 | let result = 0; 16 | let count = 0; 17 | 18 | let cb = (item) => { 19 | if (item) { 20 | let v = item instanceof Item ? item.get(attr) : item[attr]; 21 | if (v) { 22 | result = result + v; 23 | } 24 | count++; 25 | } 26 | }; 27 | 28 | if (cond) { 29 | return skipper(col, cond, cb).then(() => result / count); 30 | } 31 | col.forEach(cb); 32 | return result / count; 33 | }, 34 | 'avg' 35 | ); 36 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/count.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./oper'); 6 | const skipper = require('./skipper'); 7 | const p = require('./processed'); 8 | 9 | /** 10 | * @param {DataRepository} dataRepo 11 | * @returns {Function} 12 | */ 13 | module.exports = c( 14 | function (col, cond, unique) { 15 | let result = 0; 16 | let processed = p(); 17 | 18 | let cb = (item) => { 19 | if (item) { 20 | if (unique && processed(item)) { 21 | return; 22 | } 23 | result++; 24 | } 25 | }; 26 | 27 | if (cond) { 28 | return skipper(col, cond, cb).then(() => result); 29 | } 30 | col.forEach(cb); 31 | return result; 32 | }, 33 | 'count' 34 | ); 35 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | sum: require('./sum'), 8 | count: require('./count'), 9 | avg: require('./avg'), 10 | max: require('./max'), 11 | min: require('./min'), 12 | merge: require('./merge') 13 | }; 14 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/max.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./oper'); 6 | const skipper = require('./skipper'); 7 | const Item = require('core/interfaces/DataRepository').Item; 8 | 9 | /** 10 | * @param {DataRepository} dataRepo 11 | * @returns {Function} 12 | */ 13 | module.exports = c( 14 | (col, attr, cond) => { 15 | if (!col.length) { 16 | return null; 17 | } 18 | let result = 0; 19 | 20 | let cb = (item) => { 21 | if (item) { 22 | let v = item instanceof Item ? item.get(attr) : item[attr]; 23 | if (v > result) { 24 | result = v; 25 | } 26 | } 27 | }; 28 | 29 | if (cond) { 30 | return skipper(col, cond, cb).then(() => result); 31 | } 32 | col.forEach(cb); 33 | return result; 34 | }, 35 | 'max' 36 | ); 37 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/merge.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 14.07.17. 3 | */ 4 | 'use strict'; 5 | const c = require('./oper'); 6 | const skipper = require('./skipper'); 7 | const Item = require('core/interfaces/DataRepository').Item; 8 | const p = require('./processed'); 9 | 10 | // jshint maxcomplexity: 20, maxstatements: 30 11 | 12 | function work(col, attr, cond, unique, sep) { 13 | let result = ''; 14 | sep = sep || ' '; 15 | if (Array.isArray(col)) { 16 | let processed = p(); 17 | 18 | let cb = (item) => { 19 | if (item !== null) { 20 | let v = null; 21 | if (attr.indexOf('.') > 0) { 22 | let att = attr.substr(0, attr.indexOf('.')); 23 | let satt = attr.substr(attr.indexOf('.') + 1); 24 | v = item instanceof Item ? item.property(att).evaluate() : item[att]; 25 | if (!Array.isArray(v)) { 26 | v = [v]; 27 | } 28 | v = work(v, satt, null, unique, sep); 29 | } else { 30 | v = item instanceof Item ? item.get(attr) : item[attr]; 31 | } 32 | 33 | if (v) { 34 | if (unique && processed(v)) { 35 | return; 36 | } 37 | result = result + (result ? sep : '') + v; 38 | } 39 | } 40 | }; 41 | 42 | if (cond) { 43 | return skipper(col, cond, cb).then(() => result); 44 | } 45 | 46 | col.forEach(cb); 47 | } 48 | return result; 49 | } 50 | 51 | 52 | /** 53 | * @param {DataRepository} dataRepo 54 | * @returns {Function} 55 | */ 56 | module.exports = c(work, 'sum'); 57 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./oper'); 6 | const skipper = require('./skipper'); 7 | const Item = require('core/interfaces/DataRepository').Item; 8 | 9 | /** 10 | * @param {DataRepository} dataRepo 11 | * @returns {Function} 12 | */ 13 | module.exports = c( 14 | function (col, attr, cond) { 15 | if (!col.length) { 16 | return null; 17 | } 18 | let result = Number.POSITIVE_INFINITY; 19 | let cb = (item) => { 20 | if (item) { 21 | let v = item instanceof Item ? item.get(attr) : item[attr]; 22 | if (v < result) { 23 | result = v; 24 | } 25 | } 26 | }; 27 | 28 | if (cond) { 29 | return skipper(col, cond, cb).then(() => result); 30 | } 31 | 32 | col.forEach(cb); 33 | return result; 34 | }, 35 | 'max' 36 | ); 37 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/processed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 17.07.17. 3 | */ 4 | 5 | const Item = require('core/interfaces/DataRepository').Item; 6 | 7 | module.exports = function () { 8 | let processed = []; 9 | return function (v) { 10 | if (v instanceof Item) { 11 | v = v.getItemId(); 12 | } 13 | if (processed.indexOf(v) < 0) { 14 | processed.push(v); 15 | return false; 16 | } else { 17 | return true; 18 | } 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/skipper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 10.01.19. 3 | */ 4 | 5 | module.exports = function (col, cond, cb) { 6 | let p = Promise.resolve(); 7 | col.forEach((item) => { 8 | p = p.then(() => cond.apply(item)).then(apply => apply ? cb(item) : null); 9 | }); 10 | return p; 11 | } -------------------------------------------------------------------------------- /core/impl/Calculator/func/aggreg/sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./oper'); 6 | const skipper = require('./skipper'); 7 | const Item = require('core/interfaces/DataRepository').Item; 8 | const p = require('./processed'); 9 | 10 | // jshint maxstatements: 30, maxcomplexity: 20 11 | function work(col, attr, cond, unique) { 12 | let result = 0; 13 | let processed = p(); 14 | if (Array.isArray(col)) { 15 | let cb = (item) => { 16 | if (item !== null) { 17 | if (unique && processed(item)) { 18 | return; 19 | } 20 | 21 | let v = null; 22 | if (attr.indexOf('.') > 0) { 23 | let att = attr.substr(0, attr.indexOf('.')); 24 | let satt = attr.substr(attr.indexOf('.') + 1); 25 | v = item instanceof Item ? item.property(att).evaluate() : item[att]; 26 | if (!Array.isArray(v)) { 27 | v = [v]; 28 | } 29 | v = work(v, satt, null, unique); 30 | } else { 31 | v = item instanceof Item ? item.get(attr) : item[attr]; 32 | } 33 | 34 | if (v !== null) { 35 | result = result + v; 36 | } 37 | } 38 | }; 39 | 40 | if (cond) { 41 | return skipper(col, cond, cb).then(() => result); 42 | } 43 | col.forEach(cb); 44 | } 45 | return result; 46 | } 47 | 48 | /** 49 | * @param {DataRepository} dataRepo 50 | * @returns {Function} 51 | */ 52 | module.exports = c(work, 'sum'); 53 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arithmetic/add.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./incOper'); 6 | 7 | module.exports = c(function (a, b) {return a + b;}, 0); 8 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arithmetic/decOper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | 7 | function countResult(args, cb) { 8 | if (!args.length) { 9 | return 0; 10 | } 11 | var result = args[0]; 12 | for (var i = 1; i < args.length; i++) { 13 | result = cb(result, args[i]); 14 | } 15 | return result; 16 | } 17 | 18 | module.exports = function (cb) { 19 | return function (args) { 20 | return function () { 21 | return calc(this, args, null, function (args) { 22 | return countResult(args, cb); 23 | }); 24 | }; 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arithmetic/div.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./decOper'); 6 | 7 | module.exports = c(function (a, b) {return a / b;}); 8 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arithmetic/incOper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | 7 | function countResult(args, start, cb) { 8 | var result = start; 9 | for (var i = 0; i < args.length; i++) { 10 | result = cb(result, args[i]); 11 | } 12 | return result; 13 | } 14 | 15 | module.exports = function (cb, start) { 16 | return function (args) { 17 | return function () { 18 | return calc(this, args, null, function (args) { 19 | return countResult(args, start, cb); 20 | }); 21 | }; 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arithmetic/mul.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./incOper'); 6 | 7 | module.exports = c(function (a, b) {return a * b;}, 1); 8 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arithmetic/round.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 10.02.17. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | const {round10} = require('expected-round'); 7 | 8 | function round(args) { 9 | let v1, v2; 10 | if (!args.length) { 11 | return 0; 12 | } 13 | v1 = parseFloat(args[0]); 14 | 15 | if (!Number.isFinite(v1)) { 16 | return v1; 17 | } 18 | 19 | v2 = 0; 20 | if (args.length > 1 && !isNaN(args[1])) { 21 | v2 = args[1]; 22 | } 23 | return round10(v1, -(v2)); 24 | } 25 | 26 | module.exports = function (args) { 27 | return function () { 28 | return calc(this, args, null, function (args) { 29 | return round(args); 30 | }); 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arithmetic/sub.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./decOper'); 6 | 7 | module.exports = c(function (a, b) {return a - b;}); 8 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/arrays/element.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 25.09.17. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | 7 | module.exports = function (args) { 8 | return function () { 9 | return calc(this, args, null, 10 | function (args) { 11 | let arr = []; 12 | let ind = 0; 13 | if (args.length > 0) { 14 | if (Array.isArray(args[0])) { 15 | arr = args[0]; 16 | } 17 | } 18 | if (args.length > 1) { 19 | ind = args[1]; 20 | if (ind === 'last') { 21 | ind = arr.length - 1; 22 | } 23 | } 24 | if (typeof arr[ind] !== 'undefined') { 25 | return arr[ind]; 26 | } 27 | return null; 28 | } 29 | ); 30 | }; 31 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/arrays/in.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | module.exports = function (args) { 5 | return function () { 6 | return calc(this, args, null, 7 | function (args) { 8 | let arr = []; 9 | let v = args.length ? args[0] : null; 10 | if (args.length > 1) { 11 | if (Array.isArray(args[1])) { 12 | arr = args[1]; 13 | } 14 | } 15 | return arr.indexOf(v) >= 0; 16 | } 17 | ); 18 | }; 19 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/bool/and.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const chain = require('../util').sequenceCheck; 6 | 7 | module.exports = function (args) { 8 | return function () { 9 | return chain(this, args, false); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/bool/not.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | 7 | function operation(args) { 8 | var result = false; 9 | if (args.length === 1) { 10 | result = !args[0]; 11 | } 12 | return result; 13 | } 14 | 15 | module.exports = function (args) { 16 | return function () { 17 | return calc(this, args, 1, operation); 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/bool/or.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const chain = require('../util').sequenceCheck; 6 | 7 | module.exports = function (args) { 8 | return function () { 9 | return chain(this, args, true); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/cmpOper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | 7 | function operation(args, cb) { 8 | let result = false; 9 | let v1, v2; 10 | if (args.length === 2) { 11 | v1 = args[0] instanceof Date ? args[0].getTime() : args[0]; 12 | v2 = args[1] instanceof Date ? args[1].getTime() : args[1]; 13 | result = cb(v1, v2); 14 | } 15 | return result; 16 | } 17 | 18 | module.exports = function (cb) { 19 | return function (args) { 20 | return function () { 21 | return calc(this, args, 2, function (args) {return operation(args, cb);}); 22 | }; 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/empty.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | module.exports = function (args) { 5 | return function () { 6 | return calc(this, args, 2, function (args) { 7 | return typeof args[0] === 'undefined' || args[0] === null || Array.isArray(args[0]) && !args[0].length; 8 | }); 9 | }; 10 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/eq.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | 6 | // jshint eqeqeq: false 7 | 8 | const c = require('./cmpOper'); 9 | const Item = require('core/interfaces/DataRepository').Item; 10 | 11 | module.exports = c(function (a, b) { 12 | if (a instanceof Item && b instanceof Item) { 13 | a = a.getClassName() + '@' + a.getItemId(); 14 | b = b.getClassName() + '@' + b.getItemId(); 15 | } else { 16 | if (a instanceof Item) { 17 | a = a.getItemId(); 18 | } 19 | 20 | if (b instanceof Item) { 21 | b = b.getItemId(); 22 | } 23 | } 24 | return a == b; 25 | }); 26 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/gt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./cmpOper'); 6 | module.exports = c(function (a, b) {return a > b;}); 7 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/gte.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./cmpOper'); 6 | module.exports = c(function (a, b) {return a >= b;}); 7 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/lt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./cmpOper'); 6 | module.exports = c(function (a, b) {return a < b;}); 7 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/lte.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./cmpOper'); 6 | module.exports = c(function (a, b) {return a <= b;}); 7 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/ne.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('./cmpOper'); 6 | module.exports = c(function (a, b) {return a !== b;}); 7 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/cmp/nempty.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | module.exports = function (args) { 5 | return function () { 6 | return calc(this, args, 2, function (args) { 7 | return !(typeof args[0] === 'undefined' || args[0] === null || Array.isArray(args[0]) && !args[0].length); 8 | }); 9 | }; 10 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/condition/if.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 3/30/17. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | 7 | module.exports = function (args) { 8 | return function () { 9 | return calc( 10 | this, 11 | args, 12 | 1, 13 | cond => cond[0] ? calc(this, [args[1]], 1, r => r[0]) : calc(this, [args[2]], 1, r => r[0]) 14 | ); 15 | }; 16 | }; 17 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/data/contains.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | const chain = require('../util').sequenceCheck; 4 | 5 | var contains = function (args) { 6 | return function () { 7 | return calc(this, args, 2, function (args) { 8 | if (Array.isArray(args[0]) && args.length > 1) { 9 | let checkerConstructor = args[1]; 10 | if (typeof checkerConstructor === 'function') { 11 | let checkers = []; 12 | for (let i = 0; i < args[0].length; i++) { 13 | let item = args[0][i]; 14 | checkers.push(checkerConstructor.apply(item)); 15 | } 16 | return chain(this, checkers, true); 17 | } 18 | } 19 | return false; 20 | }); 21 | }; 22 | }; 23 | 24 | contains.byRefMask = [1]; 25 | 26 | module.exports = contains; 27 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/data/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 15.06.17. 3 | */ 4 | module.exports = { 5 | get: require('./get.js') 6 | }; 7 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/data/size.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | module.exports = function (args) { 5 | return function () { 6 | return calc(this, args, 1, 7 | function (args) { 8 | if (args.length > 0 && args[0]) { 9 | if (Array.isArray(args[0]) || typeof args[0] === 'string') { 10 | return args[0].length; 11 | } 12 | return String(args[0]).length; 13 | } 14 | return 0; 15 | } 16 | ); 17 | }; 18 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/date/date.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const moment = require('moment'); 3 | const calc = require('../util').calculate; 4 | 5 | module.exports = function (args) { 6 | return function () { 7 | return calc(this, args, 3, function ([s, format, lang]) { 8 | if (!s) { 9 | return null; 10 | } 11 | let d = moment(s, format, lang); 12 | if (d.isValid()) { 13 | return d.toDate(); 14 | } 15 | return null; 16 | }); 17 | }; 18 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/date/dateAdd.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const moment = require('moment'); 6 | const calc = require('../util').calculate; 7 | 8 | function countResult(args) { 9 | var v1, v2, v3; 10 | v1 = null; 11 | if (args.length) { 12 | v1 = moment(args[0]); 13 | v2 = 0; 14 | if (args.length > 1 && !isNaN(args[1])) { 15 | v2 = args[1]; 16 | } 17 | v3 = 'd'; 18 | if (args.length > 2) { 19 | v3 = String(args[2]); 20 | } 21 | return v1.add(v2, v3).toDate(); 22 | } else { 23 | return new Date(); 24 | } 25 | } 26 | 27 | module.exports = function (args) { 28 | return function () { 29 | return calc(this, args, 3, countResult); 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/date/dateDiff.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const moment = require('moment'); 6 | const calc = require('../util').calculate; 7 | 8 | function countResult(args) { 9 | var v1, v2, v3; 10 | v1 = 'days'; 11 | if (args.length) { 12 | v1 = String(args[0]); 13 | } 14 | if (args.length > 1) { 15 | v2 = moment(args[1]); 16 | } else { 17 | v2 = moment(); 18 | } 19 | if (args.length > 2) { 20 | v3 = moment(args[2]); 21 | } else { 22 | v3 = moment(); 23 | } 24 | return v2.diff(v3, v1); 25 | } 26 | 27 | module.exports = function (args) { 28 | return function () { 29 | return calc(this, args, 3, countResult); 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/date/dateFormat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 19.04.17. 3 | */ 4 | 'use strict'; 5 | const moment = require('moment'); 6 | const calc = require('../util').calculate; 7 | 8 | module.exports = function (args) { 9 | return function () { 10 | return calc(this, args, 3, function ([date, format, lang]) { 11 | if (!date) { 12 | return ''; 13 | } 14 | var d = moment(date); 15 | if (lang) { 16 | d.locale(lang); 17 | } 18 | return d.format(String(format || 'L')); 19 | }); 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/date/now.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = function () { 7 | return function () { 8 | return new Date(); 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | and: require('./bool/and'), 8 | or: require('./bool/or'), 9 | not: require('./bool/not'), 10 | eq: require('./cmp/eq'), 11 | ne: require('./cmp/ne'), 12 | lt: require('./cmp/lt'), 13 | gt: require('./cmp/gt'), 14 | lte: require('./cmp/lte'), 15 | gte: require('./cmp/gte'), 16 | add: require('./arithmetic/add'), 17 | mul: require('./arithmetic/mul'), 18 | sub: require('./arithmetic/sub'), 19 | div: require('./arithmetic/div'), 20 | round: require('./arithmetic/round'), 21 | obj: require('./obj'), 22 | now: require('./date/now'), 23 | date: require('./date/date'), 24 | dateAdd: require('./date/dateAdd'), 25 | dateDiff: require('./date/dateDiff'), 26 | dateFormat: require('./date/dateFormat'), 27 | format: require('./date/dateFormat'), 28 | concat: require('./string/concat'), 29 | substr: require('./string/substr'), 30 | pad: require('./string/pad'), 31 | upper: require('./string/upper'), 32 | lower: require('./string/lower'), 33 | element: require('./arrays/element'), 34 | collect: require('./process/collect'), 35 | if: require('./condition/if'), 36 | nempty: require('./cmp/nempty'), 37 | empty: require('./cmp/empty'), 38 | contains: require('./data/contains'), 39 | like: require('./string/like'), 40 | in: require('./arrays/in'), 41 | size: require('./data/size'), 42 | number2words: require('./produce/number2words') 43 | }; 44 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/obj.js: -------------------------------------------------------------------------------- 1 | /* eslint no-invalid-this: off, no-sync: off */ 2 | /** 3 | * Created by kras on 03.11.16. 4 | */ 5 | 'use strict'; 6 | const ac = require('./util').args; 7 | 8 | function countResult(args) { 9 | var result = {}; 10 | var i, nm; 11 | nm = null; 12 | for (i = 0; i < args.length; i++) { 13 | if (i % 2 === 0) { 14 | nm = args[i]; 15 | result[nm] = null; 16 | } else if (nm) { 17 | result[nm] = args[i]; 18 | nm = null; 19 | } 20 | } 21 | return result; 22 | } 23 | 24 | module.exports = function (args) { 25 | return function () { 26 | let result = ac(this, args); 27 | if (result instanceof Promise) { 28 | return result.then(cArgs => countResult(cArgs)); 29 | } 30 | return countResult(result); 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/process/collect.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | function processArg(arg, result) { 5 | if (Array.isArray(arg)) { 6 | arg.forEach((arg) => processArg(arg, result)); 7 | } else if (arg !== null) { 8 | result.push(arg); 9 | } 10 | } 11 | 12 | module.exports = function (args) { 13 | return function () { 14 | return calc(this, args, null, function (args) { 15 | let result = []; 16 | args.forEach((arg) => processArg(arg, result)); 17 | return result; 18 | }); 19 | }; 20 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/produce/number2words.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const number2words = require('core/util/number2words'); 3 | const calc = require('../util').calculate; 4 | 5 | module.exports = function (args) { 6 | return function () { 7 | return calc(this, args, null, 8 | function (args) { 9 | return numbers2words(args[0], args[1]); 10 | } 11 | ); 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/sequence/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | next: require('./next') 3 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/sequence/next.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | const {t} = require('core/i18n'); 4 | 5 | /** 6 | * @param {SequenceProvider} sp 7 | * @returns {Function} 8 | */ 9 | module.exports = function (sp) { 10 | return function (args) { 11 | return function () { 12 | return calc(this, args, 1, function (args) { 13 | if (args.length > 0) { 14 | return sp.next(args[0]); 15 | } else { 16 | throw new Error(t('Sequence name not specified!')); 17 | } 18 | }); 19 | }; 20 | }; 21 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/string/concat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const c = require('../arithmetic/incOper'); 6 | 7 | function s(v) { 8 | return (v === null || v === false || typeof v === 'undefined') ? '' : String(v); 9 | } 10 | 11 | module.exports = c((a, b) => s(a) + s(b), ''); 12 | 13 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/string/like.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | module.exports = function (args) { 5 | return function () { 6 | return calc(this, args, null, 7 | function (args) { 8 | let re = new RegExp(args[1]); 9 | return re.test(args[0]); 10 | } 11 | ); 12 | }; 13 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/string/lower.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | module.exports = function (args) { 5 | return function () { 6 | return calc(this, args, 1, ([v]) => { 7 | return String(v).toLowerCase(); 8 | }); 9 | }; 10 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/string/pad.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | function pad(args) { 5 | var v1, v2, v3, v4; 6 | v1 = ''; 7 | if (args.length) { 8 | v1 = String(args[0] || ''); 9 | } 10 | v2 = 0; 11 | if (args.length > 1 && !isNaN(args[1])) { 12 | v2 = parseInt(args[1]); 13 | } 14 | v3 = '0'; 15 | if (args.length > 2) { 16 | v3 = String(args[2]); 17 | } 18 | v4 = 'l'; 19 | if (args.length > 3 && (args[3] === 'l' || args[3] === 'r')) { 20 | v4 = args[3]; 21 | } 22 | 23 | let n = v1.length; 24 | while (v2 > n) { 25 | if (v4 === 'l') { 26 | v1 = v3 + v1; 27 | } else { 28 | v1 = v1 + v3; 29 | } 30 | v2--; 31 | } 32 | 33 | return v1; 34 | } 35 | 36 | module.exports = function (args) { 37 | return function () { 38 | return calc(this, args, 3, pad); 39 | }; 40 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/func/string/substr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | const calc = require('../util').calculate; 6 | 7 | function countResult(args) { 8 | var v1, v2, v3; 9 | v1 = ''; 10 | if (args.length) { 11 | v1 = String(args[0] || ''); 12 | } 13 | v2 = 0; 14 | if (args.length > 1 && !isNaN(args[1])) { 15 | v2 = args[1]; 16 | } 17 | v3 = v1.length; 18 | if (args.length > 2 && !isNaN(args[2])) { 19 | v3 = args[2]; 20 | } 21 | return v1.substr(v2, v3); 22 | } 23 | 24 | module.exports = function (args) { 25 | return function () { 26 | return calc(this, args, 3, countResult); 27 | }; 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /core/impl/Calculator/func/string/upper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const calc = require('../util').calculate; 3 | 4 | module.exports = function (args) { 5 | return function () { 6 | return calc(this, args, 1, ([v]) => { 7 | return String(v).toUpperCase(); 8 | }); 9 | }; 10 | }; -------------------------------------------------------------------------------- /core/impl/Calculator/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | 6 | const ICalculator = require('core/interfaces/Calculator'); 7 | const stdLib = require('./func'); 8 | const clone = require('clone'); 9 | const aggreg = require('./func/aggreg'); 10 | const data = require('./func/data'); 11 | const sequence = require('./func/sequence'); 12 | const SequenceProvider = require('core/interfaces/SequenceProvider'); 13 | const parser = require('./func/parser'); 14 | 15 | /** 16 | * @param {{}} options 17 | * @param {DataRepository | String} options.dataRepo 18 | * @param {SequenceProvider} options.sequenceProvider 19 | * @param {Logger} [options.log] 20 | * @constructor 21 | */ 22 | function Calculator(options) { 23 | 24 | let funcLib = clone(stdLib); 25 | 26 | if (options.dataRepo) { 27 | funcLib.sum = aggreg.sum(options.dataRepo); 28 | funcLib.count = aggreg.count(options.dataRepo); 29 | funcLib.avg = aggreg.avg(options.dataRepo); 30 | funcLib.max = aggreg.max(options.dataRepo); 31 | funcLib.min = aggreg.min(options.dataRepo); 32 | funcLib.merge = aggreg.merge(options.dataRepo); 33 | funcLib.get = data.get(options.dataRepo); 34 | } 35 | if (options.sequenceProvider instanceof SequenceProvider) { 36 | funcLib.next = sequence.next(options.sequenceProvider); 37 | } 38 | 39 | /** 40 | * @param {String | {}} formula 41 | */ 42 | this._parseFormula = function (formula, moptions) { 43 | return parser(formula, funcLib, () => options.dataRepo, moptions || {}); 44 | }; 45 | } 46 | 47 | Calculator.prototype = new ICalculator(); 48 | 49 | module.exports = Calculator; 50 | -------------------------------------------------------------------------------- /core/impl/EventManager.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 10/18/16. 3 | */ 4 | 5 | function EventManager() { 6 | 7 | var listeners = {}; 8 | 9 | this.on = function (event, func) { 10 | if (Array.isArray(event)) { 11 | event.forEach(e => this.on(e, func)); 12 | } else { 13 | if (!listeners[event]) { 14 | listeners[event] = []; 15 | } 16 | listeners[event].push(func); 17 | } 18 | }; 19 | 20 | this.trigger = function (event) { 21 | if (listeners[event.type]) { 22 | const results = []; 23 | let promises = Promise.resolve(); 24 | try { 25 | listeners[event.type].forEach((listener) => { 26 | promises = promises 27 | .then(() => listener(event)) 28 | .then((result) => { 29 | if (typeof result !== 'undefined') { 30 | results.push(result); 31 | } 32 | }); 33 | }); 34 | } catch (err) { 35 | return Promise.reject(err); 36 | } 37 | return promises 38 | .then( 39 | () => { 40 | event.results = results; 41 | return event; 42 | } 43 | ); 44 | } else { 45 | return Promise.resolve(event); 46 | } 47 | }; 48 | } 49 | 50 | module.exports = EventManager; 51 | -------------------------------------------------------------------------------- /core/impl/QueryParser/classes.js: -------------------------------------------------------------------------------- 1 | class Attr { 2 | 3 | constructor(value) { 4 | this.val = value; 5 | } 6 | 7 | set value(v) { 8 | this.val = v; 9 | } 10 | 11 | get value() { 12 | if (this.val) { 13 | if (this.val[0] === '$') { 14 | return this.val.substr(1); 15 | } 16 | return this.val; 17 | } 18 | } 19 | } 20 | 21 | module.exports.Attr = Attr; 22 | -------------------------------------------------------------------------------- /core/impl/QueryParser/test/grammar.spec.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const grammar = require('../grammar'); 3 | const nearley = require('nearley'); 4 | const F = require('../../../FunctionCodes'); 5 | 6 | function parse(query) { 7 | const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar)); 8 | const results = parser.feed(query).results; 9 | if (results.length === 0) { 10 | throw new Error('Found no parsings.'); 11 | } 12 | 13 | if (results.length > 1) { 14 | throw new Error('Ambiguous results.'); 15 | } 16 | return results[0]; 17 | } 18 | 19 | const queries = [{ 20 | query: 'propertyName = 11', 21 | result: {[F.EQUAL]: [{val: 'propertyName'}, 11]} 22 | },{ 23 | query: 'propertyName = "some text"', 24 | result: {[F.EQUAL]: [{val: 'propertyName'}, 'some text']} 25 | },{ 26 | query: '`Attribute` = 11', 27 | result: {[F.EQUAL]: [{val: 'Attribute'}, 11]} 28 | },{ 29 | query: '`Attribute` = "some text"', 30 | result: {[F.EQUAL]: [{val: 'Attribute'}, 'some text']} 31 | },{ 32 | query: 'propertyName LIKE "some text"', 33 | result: {[F.LIKE]: [{val: 'propertyName'}, 'some text']} 34 | },{ 35 | query: '1 != "some text"', 36 | result: {[F.NOT_EQUAL]: [1, 'some text']} 37 | },{ 38 | query: 'prop1 >= 11 AND `attr2` LIKE "test"', 39 | result: {[F.AND]: [ 40 | {[F.GREATER_OR_EQUAL]: [{val: 'prop1'}, 11]}, 41 | {[F.LIKE]: [{val: 'attr2'}, 'test']} 42 | ]} 43 | },{ 44 | query: '(prop1 >= 11 AND `attr2` LIKE "test") OR prop3 != "blabla"', 45 | result: {[F.OR]: [ 46 | {[F.AND]: [ 47 | {[F.GREATER_OR_EQUAL]: [{val: 'prop1'}, 11]}, 48 | {[F.LIKE]: [{val: 'attr2'}, 'test']} 49 | ]}, 50 | {[F.NOT_EQUAL]: [{val: 'prop3'}, 'blabla']} 51 | ]} 52 | }]; 53 | 54 | describe('Тестирование nearley-грамматики парсера запросов', () => { 55 | queries.forEach(q => it(q.query, () => assert.deepEqual(parse(q.query), q.result))); 56 | }); 57 | -------------------------------------------------------------------------------- /core/impl/cache/CacheProxy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by inkz on 10/6/16. 3 | */ 4 | 'use strict'; 5 | 6 | const Repository = require('core/interfaces/Repository'); 7 | 8 | /** 9 | * @constructor 10 | */ 11 | function CacheProxy() { 12 | 13 | /** 14 | * 15 | * @param {String} key 16 | * @returns {Promise} 17 | * @private 18 | */ 19 | this._get = function (key) { 20 | return Promise.resolve(null); 21 | }; 22 | 23 | /** 24 | * 25 | * @param {String} key 26 | * @param {*} value 27 | * @returns {Promise} 28 | * @private 29 | */ 30 | this._set = function (key, value) { 31 | return Promise.resolve(); 32 | }; 33 | } 34 | 35 | CacheProxy.prototype = new Repository(); 36 | module.exports = CacheProxy; 37 | -------------------------------------------------------------------------------- /core/impl/cache/DsCacheRepository.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 07.11.18. 3 | */ 4 | 'use strict'; 5 | 6 | const Repository = require('core/interfaces/Repository'); 7 | const F = require('core/FunctionCodes'); 8 | 9 | /** 10 | * 11 | * @param {{dataSource: DataSource, name: String}} config 12 | * @constructor 13 | */ 14 | function DsCacheRepository(config) { 15 | 16 | const tableName = 'ion_cache_' + config.name; 17 | 18 | 19 | /** 20 | * 21 | * @param {String} key 22 | * @returns {Promise} 23 | * @private 24 | */ 25 | this._get = function (key) { 26 | return config.dataSource.get(tableName, {[F.EQUAL]: ['$name', key]}).then(rec => rec ? rec.value : null); 27 | }; 28 | 29 | /** 30 | * 31 | * @param {String} key 32 | * @param {*} value 33 | * @returns {Promise} 34 | * @private 35 | */ 36 | this._set = function (key, value) { 37 | return config.dataSource.upsert(tableName, {[F.EQUAL]: ['$name', key]}, {name: key, value: value}); 38 | }; 39 | 40 | this.init = function () { 41 | return config.dataSource.ensureIndex(tableName, {name: 1}, {unique: true}); 42 | }; 43 | } 44 | 45 | DsCacheRepository.prototype = new Repository(); 46 | module.exports = DsCacheRepository; 47 | -------------------------------------------------------------------------------- /core/impl/cache/InnerCacheRepository.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 10/8/16. 3 | */ 4 | 'use strict'; 5 | 6 | const Repository = require('core/interfaces/Repository'); 7 | 8 | /** 9 | * 10 | * @param {Object} config 11 | * @constructor 12 | */ 13 | function InnerCacheRepository() { 14 | 15 | const cache = {}; 16 | 17 | /** 18 | * 19 | * @param {String} key 20 | * @returns {Promise} 21 | * @private 22 | */ 23 | this._get = function (key) { 24 | return Promise.resolve(cache[key]); 25 | }; 26 | 27 | /** 28 | * 29 | * @param {String} key 30 | * @param {*} value 31 | * @returns {Promise} 32 | * @private 33 | */ 34 | this._set = function (key, value) { 35 | cache[key] = value; 36 | return Promise.resolve(); 37 | }; 38 | 39 | } 40 | 41 | InnerCacheRepository.prototype = new Repository(); 42 | module.exports = InnerCacheRepository; 43 | -------------------------------------------------------------------------------- /core/impl/changelogger/DsChangelogFactory.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 19.07.16. 3 | */ 4 | 'use strict'; 5 | const {t} = require('core/i18n'); 6 | 7 | var DsChangeLogger = require('./DsChangeLogger'); 8 | 9 | function DsChangeLogFactory(options) { 10 | this.ds = options.dataSource; 11 | 12 | if (!this.ds) { 13 | throw new Error(t('Datasource not specified for changelogger factory!')); 14 | } 15 | 16 | this.logger = function (authCallback) { 17 | return new DsChangeLogger(this.ds, authCallback); 18 | }; 19 | } 20 | 21 | module.exports = DsChangeLogFactory; 22 | -------------------------------------------------------------------------------- /core/impl/email/NodeMailer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 27.03.19. 3 | */ 4 | const IEmailSender = require('core/interfaces/EmailSender'); 5 | const nodemailer = require('nodemailer'); 6 | 7 | class NodeMailer extends IEmailSender { 8 | /** 9 | * @param {{}} options 10 | * @param {{}} options.transport 11 | */ 12 | constructor(options) { 13 | super(); 14 | this.transport = nodemailer.createTransport(options.transport); 15 | } 16 | 17 | /** 18 | * @param {String} from 19 | * @param {String | Stringp[]} to 20 | * @param {{subject: String, html: String, plain: String}} message 21 | * @returns {*} 22 | */ 23 | _send(from, to, message) { 24 | let letter = { 25 | from: from, 26 | to: to, 27 | subject: message.subject || '' 28 | }; 29 | letter.html = message.html; 30 | letter.text = message.plain; 31 | return this.transport.sendMail(letter); 32 | } 33 | } 34 | 35 | module.exports = NodeMailer; 36 | -------------------------------------------------------------------------------- /core/impl/email/SendMail.js: -------------------------------------------------------------------------------- 1 | const IEmailSender = require('core/interfaces/EmailSender'); 2 | const sendmail = require('sendmail'); 3 | const merge = require('merge'); 4 | 5 | class SendMail extends IEmailSender { 6 | /** 7 | * @param {{}} options 8 | * @param {Logger} options.log 9 | * @param {{}} [options.settings] 10 | */ 11 | constructor(options) { 12 | super(); 13 | this.log = options.log; 14 | let opts = merge({silent: true}, options.settings || {}); 15 | if (this.log) { 16 | opts.logger = { 17 | debug: this.log.log, 18 | info: this.log.info, 19 | warn: this.log.warn, 20 | error: this.log.error 21 | }; 22 | } 23 | this.sender = sendmail(opts); 24 | } 25 | 26 | /** 27 | * @param {String} from 28 | * @param {String | String[]} to 29 | * @param {{subject: String, html: String, plain: String}} message 30 | * @returns {*} 31 | */ 32 | _send(from, to, message) { 33 | let letter = { 34 | from: from, 35 | to: to, 36 | subject: message.subject || '' 37 | }; 38 | letter.html = message.html; 39 | letter.text = message.plain; 40 | return new Promise((resolve, reject) => { 41 | this.sender(letter, (err, reply) => err ? reject(err) : resolve(reply)); 42 | }); 43 | } 44 | } 45 | 46 | module.exports = SendMail; 47 | 48 | -------------------------------------------------------------------------------- /core/impl/log/LogRecorder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 06.10.16. 3 | */ 4 | 'use strict'; 5 | const Logger = require('core/interfaces/Logger'); 6 | 7 | /** 8 | * @param {{}} options 9 | * @param {IonLogger} options.target 10 | * @param {String[]} options.messageTypes 11 | * @constructor 12 | */ 13 | function LogRecorder(options) { 14 | 15 | var recording = false; 16 | 17 | var buf = []; 18 | 19 | if (options && options.target) { 20 | options.target.addDestination(this, options.messageTypes || []); 21 | } 22 | 23 | this.start = function () { 24 | recording = true; 25 | }; 26 | 27 | this.stop = function () { 28 | recording = false; 29 | var result = buf; 30 | buf = []; 31 | return result; 32 | }; 33 | 34 | /** 35 | * @param {String} message 36 | */ 37 | this._info = function (message) { 38 | if (recording) { 39 | buf.push({type: 'info', message: message && (message.message || message)}); 40 | } 41 | }; 42 | 43 | /** 44 | * @param {String} message 45 | */ 46 | this._log = function (message) { 47 | if (recording) { 48 | buf.push({type: 'log', message: message && (message.message || message)}); 49 | } 50 | }; 51 | 52 | /** 53 | * @param {String} message 54 | */ 55 | this._warn = function (message) { 56 | if (recording) { 57 | buf.push({type: 'warn', message: message && (message.message || message)}); 58 | } 59 | }; 60 | 61 | /** 62 | * @param {String} message 63 | */ 64 | this._error = function (message) { 65 | if (recording) { 66 | buf.push({type: 'error', message: message && (message.message || message)}); 67 | } 68 | }; 69 | } 70 | 71 | LogRecorder.prototype = new Logger(); 72 | 73 | module.exports = LogRecorder; 74 | -------------------------------------------------------------------------------- /core/impl/log/LoggerProxy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 20.07.16. 3 | */ 4 | 5 | var Logger = require('core/interfaces/Logger'); 6 | 7 | function LoggerProxy() { 8 | /** 9 | * @param {String} message 10 | */ 11 | this._info = function (message) { 12 | }; 13 | 14 | /** 15 | * @param {String} message 16 | */ 17 | this._log = function (message) { 18 | }; 19 | 20 | /** 21 | * @param {String} message 22 | */ 23 | this._warn = function (message) { 24 | }; 25 | 26 | /** 27 | * @param {String} message 28 | */ 29 | this._error = function (message) { 30 | }; 31 | } 32 | 33 | LoggerProxy.prototype = new Logger(); 34 | 35 | module.exports = LoggerProxy; 36 | -------------------------------------------------------------------------------- /core/impl/resource/OwnCloudStorage/OwnCloudError.js: -------------------------------------------------------------------------------- 1 | class OwnCloudError extends Error { 2 | /** 3 | * @param {String} message 4 | * @param {String|Number} [statusCode] 5 | */ 6 | constructor(message, statusCode, response) { 7 | super(message); 8 | this.statusCode = statusCode; 9 | this.response = response; 10 | this.name = 'OwnCloudError'; 11 | } 12 | } 13 | 14 | module.exports = OwnCloudError; 15 | -------------------------------------------------------------------------------- /core/impl/resource/OwnCloudStorage/util.js: -------------------------------------------------------------------------------- 1 | const url = require('url'); 2 | 3 | function urlResolver(uri) { 4 | if (arguments.length > 1) { 5 | let result = uri; 6 | for (let i = 1; i < arguments.length; i++) { 7 | let tmp = arguments[i]; 8 | if (tmp) { 9 | if (tmp[0] === '/') { 10 | tmp = tmp.substr(1); 11 | } 12 | result = url.resolve(result, tmp); 13 | } 14 | } 15 | return result; 16 | } 17 | return uri; 18 | } 19 | 20 | exports.urlResolver = urlResolver; 21 | 22 | function slashChecker(path) { 23 | if (path && path.slice(-1) !== '/') { 24 | return path + '/'; 25 | } 26 | return path || ''; 27 | } 28 | 29 | exports.slashChecker = slashChecker; 30 | 31 | function ensureDirSep(dir) { 32 | if (typeof dir === 'string') { 33 | return dir.replace('\\', '/'); 34 | } 35 | return dir; 36 | } 37 | 38 | exports.ensureDirSep = ensureDirSep; 39 | -------------------------------------------------------------------------------- /core/impl/settings/Settings.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable valid-jsdoc, require-jsdoc, no-underscore-dangle, object-curly-newline, no-prototype-builtins, id-length */ 2 | /** 3 | * Created by krasilneg on 25.04.19. 4 | */ 5 | 6 | const ISettingsRepository = require('core/interfaces/SettingsRepository'); 7 | 8 | /** 9 | * @param {{dataSource: DataSource, logger: Logger}} options 10 | * @constructor 11 | */ 12 | function Settings(options) { 13 | 14 | var worker; 15 | 16 | this._set = function (nm, value, options) { 17 | worker.set(nm, value, options); 18 | }; 19 | 20 | this._get = function (nm) { 21 | return worker.get(nm); 22 | }; 23 | 24 | this._apply = function () { 25 | return worker.apply(); 26 | }; 27 | 28 | /** 29 | * @param {Boolean} preserveImportant 30 | * @returns {Promise} 31 | */ 32 | this._reset = function () { 33 | return worker.reset(); 34 | }; 35 | 36 | this._init = function () { 37 | const mode = options.mode || 'files'; 38 | const RepoClass = (mode === 'db') ? 39 | require('core/impl/settings/DsSettingsRepository') : 40 | require('core/impl/settings/SettingsRepository'); 41 | worker = new RepoClass(options); 42 | return worker.init(); 43 | }; 44 | } 45 | 46 | Settings.prototype = new ISettingsRepository(); 47 | module.exports = Settings; 48 | -------------------------------------------------------------------------------- /core/impl/settings/util/merge-configs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.19. 3 | */ 4 | 5 | function array_unique(arr) { 6 | let tmp = []; 7 | return arr.filter( 8 | (e) => { 9 | let se = typeof e === 'object' ? JSON.stringify(e) : e; 10 | if (tmp.indexOf(se) >= 0) { 11 | return false; 12 | } 13 | tmp.push(se); 14 | return true; 15 | } 16 | ); 17 | } 18 | 19 | /** 20 | * @param {*} old 21 | * @param {*} val 22 | * @param {{}} [options] 23 | * @param {Boolean} [options.overrideArrays] 24 | * @returns {*} 25 | */ 26 | function smartMerge(old, val, options) { 27 | if (typeof old === typeof val) { 28 | if (old && typeof old === 'object') { 29 | if (Array.isArray(old)) { 30 | if (options && options.overrideArrays) { 31 | return val; 32 | } 33 | 34 | if (Array.isArray(val)) { 35 | for (let i = 0; i < val.length; i++) { 36 | if (old.indexOf(val[i]) < 0) { 37 | old.push(val[i]); 38 | } 39 | } 40 | } else { 41 | old.push(val); 42 | } 43 | let tmp = array_unique(old); 44 | old.splice(0, old.length); 45 | old.push(...tmp); 46 | } else { 47 | for (let nm in val) { 48 | if (val.hasOwnProperty(nm)) { 49 | old[nm] = smartMerge(old.hasOwnProperty(nm) ? old[nm] : undefined, val[nm], options); 50 | } 51 | } 52 | } 53 | return old; 54 | } 55 | } 56 | return val; 57 | } 58 | 59 | module.exports = smartMerge; 60 | -------------------------------------------------------------------------------- /core/interfaces/AccountStorage.js: -------------------------------------------------------------------------------- 1 | class AccountStorage { 2 | /** 3 | * @param {{}} data 4 | * @returns {Promise.<{User}>} 5 | */ 6 | register(data) { 7 | return this._register(data); 8 | } 9 | 10 | unregister(id) { 11 | return this._unregister(id); 12 | } 13 | 14 | profileFields() { 15 | return this._profileFields(); 16 | } 17 | 18 | validate(data) { 19 | return this._validate(data); 20 | } 21 | 22 | /** 23 | * @param {String} id 24 | * @param {String} oldPwd 25 | * @param {String} newPwd 26 | * @returns {Promise} 27 | */ 28 | setPassword(id, oldPwd, newPwd) { 29 | return this._setPassword(id, oldPwd, newPwd); 30 | } 31 | 32 | /** 33 | * @param {String} id 34 | * @param {String} [pwd] 35 | * @param {Boolean} [disabled] 36 | * @returns {Promise.<{User}>} 37 | */ 38 | get(id, pwd, disabled) { 39 | return this._get(id, pwd, disabled); 40 | } 41 | 42 | /** 43 | * @param {String} id 44 | * @param {{}} updates 45 | * @returns {*|Promise} 46 | */ 47 | set(id, updates) { 48 | return this._set(id, updates); 49 | } 50 | 51 | /** 52 | * @param {String[]} [filter] 53 | * @param {Boolean} [disabled] 54 | * @returns {Promise.<{User[]}>} 55 | */ 56 | list(filter, disabled) { 57 | return this._list(filter, disabled); 58 | } 59 | 60 | /** 61 | * @param {String} sv 62 | * @returns {Promise.<{User[]}>} 63 | */ 64 | search(sv) { 65 | return this._search(sv); 66 | } 67 | 68 | /** 69 | * @param {String} id 70 | * @returns {Promise} 71 | */ 72 | disable(id) { 73 | return this._disable(id); 74 | } 75 | 76 | /** 77 | * @param {String} id 78 | * @returns {Promise} 79 | */ 80 | enable(id) { 81 | return this._enable(id); 82 | } 83 | } 84 | 85 | module.exports = AccountStorage; -------------------------------------------------------------------------------- /core/interfaces/AclProvider.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 02.03.16. 3 | */ 4 | 'use strict'; 5 | 6 | /** 7 | * @constructor 8 | */ 9 | function AclProvider() { 10 | 11 | /** 12 | * @returns {Promise} 13 | */ 14 | this.init = function () { 15 | if (typeof this._init === 'function') { 16 | return this._init(); 17 | } 18 | return Promise.resolve(); 19 | }; 20 | 21 | /** 22 | * @param {String | User} subject 23 | * @param {String} resource 24 | * @param {String | String[]} permissions 25 | * @returns {Promise} 26 | */ 27 | this.checkAccess = function (subject, resource, permissions) { 28 | return this._checkAccess(subject, resource, permissions); 29 | }; 30 | 31 | /** 32 | * @param {String | String[] | User} subject 33 | * @param {String | String[]} resources 34 | * @param {Boolean} [skipGlobals] 35 | * @returns {Promise} 36 | */ 37 | this.getPermissions = function (subject, resources, skipGlobals) { 38 | return this._getPermissions(subject, resources, skipGlobals); 39 | }; 40 | 41 | /** 42 | * @param {String} subject 43 | * @param {String | String[]} permissions 44 | * @returns {Promise} 45 | */ 46 | this.getResources = function (subject, permissions) { 47 | return this._getResources(subject, permissions); 48 | }; 49 | 50 | /** 51 | * @param {String} subject 52 | */ 53 | this.getCoactors = function (subject) { 54 | return this._getCoactors(subject); 55 | }; 56 | } 57 | 58 | module.exports = AclProvider; 59 | -------------------------------------------------------------------------------- /core/interfaces/Calculator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 03.11.16. 3 | */ 4 | 'use strict'; 5 | 6 | function Calculator() { 7 | /** 8 | * @param {String | {}} formula 9 | * @param {{}} [options] 10 | */ 11 | this.parseFormula = function (formula, options) { 12 | return this._parseFormula(formula, options || {}); 13 | }; 14 | } 15 | 16 | module.exports = Calculator; 17 | -------------------------------------------------------------------------------- /core/interfaces/DataRepository/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (email: inkz@xakep.ru, telegram: @inkz1) on 28.04.16. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports.DataRepository = require('./DataRepository'); 7 | module.exports.Item = require('./lib/Item'); 8 | module.exports.Property = require('./lib/Property'); 9 | -------------------------------------------------------------------------------- /core/interfaces/DigitalSignManager.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 12.09.16. 3 | */ 4 | 'use strict'; 5 | 6 | function DigitalSignManager() { 7 | /** 8 | * @param {Item} item 9 | * @param {String} action 10 | * @param {String} [preprocessor] 11 | * @returns {Promise} 12 | */ 13 | this.signingAvailable = function (item, action, preprocessor) { 14 | return this._signingAvailable(item, action, preprocessor); 15 | }; 16 | 17 | /** 18 | * @param {Item} item 19 | * @param {String} [action] 20 | * @param {String} [preprocessor] 21 | * @returns {Promise} 22 | */ 23 | this.getDataForSigning = function (item, action, preprocessor) { 24 | return this._getDataForSigning(item, action, preprocessor); 25 | }; 26 | 27 | /** 28 | * @param {String} id 29 | * @param {Buffer | Buffer[]} data 30 | * @param {Buffer | Buffer[]} signature 31 | * @param {{}} [attributes] 32 | * @returns {Promise} 33 | */ 34 | this.persistSignature = function (id, data, signature, attributes) { 35 | return this._persistSignature(id, data, signature, attributes); 36 | }; 37 | 38 | /** 39 | * @param {String} [id] 40 | * @param {Date} [since] 41 | * @param {Date} [till] 42 | * @param {{}} [options] 43 | * @param {Boolean} [options.asBase64] 44 | * @returns {Promise} 45 | */ 46 | this.getSignatures = function (id, since, till, options) { 47 | return this._getSignatures(id, since, till, options); 48 | }; 49 | 50 | /** 51 | * @returns {Promise} 52 | */ 53 | this.init = function () { 54 | return this._init(); 55 | }; 56 | } 57 | 58 | module.exports = DigitalSignManager; 59 | -------------------------------------------------------------------------------- /core/interfaces/EmailSender.js: -------------------------------------------------------------------------------- 1 | class EmailSender { 2 | /** 3 | * @param {String} from 4 | * @param {String | String[]} to 5 | * @param {{subject: String, body: String, type: String}} message 6 | * @returns {Promise} 7 | */ 8 | send(from, to, message) { 9 | return this._send(from, to, message); 10 | } 11 | } 12 | 13 | module.exports = EmailSender; 14 | -------------------------------------------------------------------------------- /core/interfaces/InsertPreprocessor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 05.05.16. 3 | */ 4 | 'use strict'; 5 | 6 | function InsertPreprocessor() { 7 | /** 8 | * @param {String} classname 9 | * @param {{}} data 10 | * @returns {Promise} 11 | */ 12 | this.preProcess = function (classname, data, namespace) { 13 | return this._preProcess(classname, data, namespace); 14 | }; 15 | } 16 | 17 | module.exports = InsertPreprocessor; 18 | -------------------------------------------------------------------------------- /core/interfaces/Iterator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.02.17. 3 | */ 4 | 'use strict'; 5 | 6 | function Iterator() { 7 | /** 8 | * @returns {Promise} 9 | */ 10 | this.next = function () { 11 | return this._next(); 12 | }; 13 | 14 | /** 15 | * @returns {Number} 16 | */ 17 | this.count = function () { 18 | return this._count(); 19 | }; 20 | } 21 | 22 | module.exports = Iterator; 23 | -------------------------------------------------------------------------------- /core/interfaces/KeyProvider.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 05.05.16. 3 | */ 4 | 'use strict'; 5 | 6 | function KeyProvider() { 7 | /** 8 | * @param {ClassMeta} cm 9 | * @param {{}} data 10 | * @returns {String} 11 | */ 12 | this.formKey = function (cm, data) { 13 | return this._formKey(cm, data); 14 | }; 15 | 16 | /** 17 | * @param {ClassMeta} cm 18 | * @param {String} id 19 | * @returns {{}} 20 | */ 21 | this.keyToData = function (cm, id) { 22 | return this._keyToData(cm, id); 23 | }; 24 | 25 | /** 26 | * @param {ClassMeta} cm 27 | * @param {{}} data 28 | * @returns {{} | null} 29 | */ 30 | this.keyData = function (cm, data) { 31 | return this._keyData(cm, data); 32 | }; 33 | } 34 | 35 | module.exports = KeyProvider; 36 | -------------------------------------------------------------------------------- /core/interfaces/ListPreprocessor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 31.10.16. 3 | */ 4 | 'use strict'; 5 | 6 | function ListPreprocessor() { 7 | /** 8 | * @param {String} className 9 | * @param {{}} options 10 | * @returns {Promise} 11 | */ 12 | this.applicable = function (className, options) { 13 | return this._applicable(className, options); 14 | }; 15 | 16 | /** 17 | * @param {Item[]} list 18 | * @param {{}} options 19 | * @returns {Promise} 20 | */ 21 | this.process = function (list, options) { 22 | return this._process(list, options); 23 | }; 24 | } 25 | 26 | module.exports = ListPreprocessor; 27 | -------------------------------------------------------------------------------- /core/interfaces/Logger.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by kras on 20.07.16. 4 | */ 5 | 6 | function Logger() { 7 | /** 8 | * @param {String} message 9 | */ 10 | this.info = function (message) { 11 | this._info(message); 12 | }; 13 | 14 | /** 15 | * @param {String} message 16 | */ 17 | this.log = function (message) { 18 | this._log(message); 19 | }; 20 | 21 | /** 22 | * @param {String} message 23 | */ 24 | this.warn = function (message) { 25 | this._warn(message); 26 | }; 27 | 28 | /** 29 | * @param {String | Error | IonError} message 30 | */ 31 | this.error = function (message) { 32 | this._error(message); 33 | }; 34 | } 35 | 36 | module.exports = Logger; 37 | -------------------------------------------------------------------------------- /core/interfaces/MetaRepository/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (email: inkz@xakep.ru, telegram: @inkz1) on 12.04.16. 3 | */ 4 | var MetaRepository = require('./MetaRepository'); 5 | var ClassMeta = require('./lib/ClassMeta'); 6 | 7 | module.exports.MetaRepository = MetaRepository; 8 | module.exports.ClassMeta = ClassMeta; 9 | -------------------------------------------------------------------------------- /core/interfaces/NotificationSender.js: -------------------------------------------------------------------------------- 1 | class NotificationSender { 2 | /** 3 | * @param {User} sender 4 | * @param {User[]} recievers 5 | * @param {{subject: String, message: String}} notification 6 | * @returns {*} 7 | */ 8 | send(sender, recievers, notification) { 9 | return this._send(sender, recievers, notification); 10 | } 11 | } 12 | 13 | module.exports = NotificationSender; 14 | -------------------------------------------------------------------------------- /core/interfaces/Notifier.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class Notifier { 4 | /** 5 | * @param {{}} notification 6 | * @param {{} | String} notification.message 7 | * @param {String} [notification.sender] 8 | * @param {String[] | String} [notification.recievers] 9 | * @param {String} [notification.subject] 10 | * @param {{}} [notification.dispatch] 11 | * @returns {Promise} 12 | */ 13 | notify(notification) { 14 | return this._notify(notification); 15 | } 16 | 17 | withdraw(id) { 18 | return this._withdraw(id); 19 | } 20 | 21 | /** 22 | * @param {String} reciever 23 | * @param {String} id 24 | * @returns {Promise} 25 | */ 26 | markAsRead(reciever, id) { 27 | return this._markAsRead(reciever, id); 28 | } 29 | 30 | /** 31 | * @param {String} reciever 32 | * @returns {Promise} 33 | */ 34 | markAllAsRead(reciever) { 35 | return this._markAllAsRead(reciever); 36 | } 37 | 38 | /** 39 | * @param {String} id 40 | * @returns {Promise} 41 | */ 42 | get(id) { 43 | return this._get(id); 44 | } 45 | 46 | /** 47 | * @param {String} reciever 48 | * @param {{offset: Number, count: Number, new: Boolean, since: Date}} options 49 | * @returns {Promise} 50 | */ 51 | list(reciever, options) { 52 | return this._list(reciever, options); 53 | } 54 | } 55 | 56 | module.exports = Notifier; -------------------------------------------------------------------------------- /core/interfaces/Preprocessor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 12.09.16. 3 | */ 4 | 'use strict'; 5 | 6 | function Preprocessor() { 7 | /** 8 | * @param {Item} item 9 | * @param {{}} [options] 10 | * @returns {Promise} 11 | */ 12 | this.applicable = function (item, options) { 13 | return this._applicable(item, options); 14 | }; 15 | /** 16 | * @param {Item} item 17 | * @param {{}} options 18 | * @returns {Promise} 19 | */ 20 | this.process = function (item, options) { 21 | return this._process(item, options); 22 | }; 23 | } 24 | 25 | module.exports = Preprocessor; 26 | -------------------------------------------------------------------------------- /core/interfaces/QueryParser.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function QueryParser() { 4 | 5 | /** 6 | * @param {String} query 7 | * @param {ClassMeta} cm 8 | * @returns {{}} 9 | */ 10 | this.parse = function (query, cm) { 11 | return this._parse(query, cm); 12 | }; 13 | 14 | } 15 | 16 | module.exports = QueryParser; 17 | -------------------------------------------------------------------------------- /core/interfaces/Repository.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by inkz on 10/3/16. 3 | */ 4 | 'use strict'; 5 | 6 | /** 7 | * 8 | * @constructor 9 | */ 10 | function Repository() { 11 | 12 | /** 13 | * 14 | * @param {String} key 15 | * @returns {*} 16 | */ 17 | this.get = function (key) { 18 | return this._get(key); 19 | }; 20 | 21 | /** 22 | * 23 | * @param {String} key 24 | * @param {*} value 25 | * @returns {*} 26 | */ 27 | this.set = function (key, value) { 28 | return this._set(key, value); 29 | }; 30 | 31 | } 32 | 33 | module.exports = Repository; 34 | -------------------------------------------------------------------------------- /core/interfaces/ResourceStorage/lib/Share.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function Share(link, options) { 4 | 5 | this.getLink = function () { 6 | return link; 7 | }; 8 | 9 | /** 10 | * @returns {{}} 11 | */ 12 | this.getOptions = function () { 13 | return options; 14 | }; 15 | } 16 | 17 | module.exports = Share; 18 | -------------------------------------------------------------------------------- /core/interfaces/ResourceStorage/lib/ShareAccessLevel.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 1/9/17. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = { 7 | READ: 'read', 8 | WRITE: 'write' 9 | }; 10 | -------------------------------------------------------------------------------- /core/interfaces/ResourceStorage/lib/StoredFile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 26.07.16. 3 | */ 4 | 'use strict'; 5 | const {t} = require('core/i18n'); 6 | 7 | function StoredFile (id, link, options, streamGetter) { 8 | this.id = id; 9 | 10 | this.link = link; 11 | 12 | this.options = options; 13 | 14 | this.name = this.options.name || this.id; 15 | 16 | /** 17 | * @returns {Promise} 18 | */ 19 | this.getContents = function () { 20 | return new Promise((resolve, reject) => { 21 | if (typeof streamGetter === 'function') { 22 | try { 23 | streamGetter((err, stream) => { 24 | if (err) { 25 | return reject(err); 26 | } 27 | if (!stream) { 28 | return reject(new Error(t('Failed to obtain file reading stream.'))); 29 | } 30 | return resolve({ 31 | name: this.name, 32 | options: this.options, 33 | stream: stream 34 | }); 35 | }); 36 | } catch (err) { 37 | reject(err); 38 | } 39 | } else { 40 | reject(new Error(t('Function for getting file input stream not specified.'))); 41 | } 42 | }); 43 | }; 44 | 45 | /** 46 | * @returns {StoredFile} 47 | */ 48 | this.clone = function () { 49 | return new StoredFile(this.id, this.link, this.options, streamGetter); 50 | }; 51 | } 52 | 53 | module.exports = StoredFile; 54 | -------------------------------------------------------------------------------- /core/interfaces/ResourceStorage/lib/ThumbnailGenerator.js: -------------------------------------------------------------------------------- 1 | class ThumbnailGenerator { 2 | generate(source, options) { 3 | return this._generate(source, options); 4 | } 5 | } 6 | 7 | module.exports = ThumbnailGenerator; 8 | -------------------------------------------------------------------------------- /core/interfaces/SequenceProvider.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | function SequenceProvider () { 5 | /** 6 | * @param {String} name 7 | * @returns {Promise} 8 | */ 9 | this.next = function (name) { 10 | return this._next(name); 11 | }; 12 | 13 | /** 14 | * @param {String} name 15 | * @param {Number} [value] 16 | * @returns {Promise} 17 | */ 18 | this.reset = function (name, value) { 19 | return this._reset(name, value); 20 | }; 21 | 22 | /** 23 | * @param {String} [name] 24 | */ 25 | this.snapshot = function (name) { 26 | return this._snapshot(name); 27 | }; 28 | } 29 | 30 | module.exports = SequenceProvider; -------------------------------------------------------------------------------- /core/interfaces/SettingsRepository.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable valid-jsdoc, require-jsdoc, no-underscore-dangle */ 2 | /** 3 | * Created by krasilneg on 25.04.19. 4 | */ 5 | 6 | /** 7 | * @constructor 8 | */ 9 | function SettingsRepository() { 10 | /** 11 | * @param {String} nm 12 | * @param {*} value 13 | * @param {{}} options 14 | */ 15 | this.set = function (nm, value, options) { 16 | this._set(nm, value, options); 17 | }; 18 | 19 | this.get = function (nm) { 20 | return this._get(nm); 21 | }; 22 | 23 | this.apply = function () { 24 | return this._apply(); 25 | }; 26 | 27 | /** 28 | * @param {Boolean} preserveImportant 29 | * @returns {Promise} 30 | */ 31 | this.reset = function (preserveImportant) { 32 | return this._reset(preserveImportant); 33 | }; 34 | 35 | this.init = function () { 36 | return this._init(); 37 | }; 38 | } 39 | 40 | module.exports = SettingsRepository; 41 | -------------------------------------------------------------------------------- /core/interfaces/WorkflowProvider.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 24.10.16. 3 | */ 4 | 'use strict'; 5 | 6 | function WorkflowProvider() { 7 | /** 8 | * @param {Item} item 9 | * @param {{uid: User, lang: String}} options 10 | * @returns {Promise} 11 | */ 12 | this.getStatus = function (item, options) { 13 | return this._getStatus(item, options || {}); 14 | }; 15 | 16 | /** 17 | * @param {String} workflow 18 | * @param {String} status 19 | * @returns {Promise} 20 | */ 21 | this.itemsInStatus = function (workflow, status) { 22 | return this._itemsInStatus(workflow, status); 23 | }; 24 | 25 | /** 26 | * @param {Item} item 27 | * @param {String} workflow 28 | * @param {String} name 29 | * @param {{}} [options] 30 | * @param {User} [options.user] 31 | * @param {ChangeLogger} [options.changeLogger] 32 | * @returns {Promise} 33 | */ 34 | this.performTransition = function (item, workflow, name, options) { 35 | return this._performTransition(item, workflow, name, options || {}); 36 | }; 37 | 38 | /** 39 | * @param {Item} item 40 | * @param {String} workflow 41 | * @param {String} state 42 | * @param {{}} [options] 43 | * @param {User} [options.user] 44 | * @param {ChangeLogger} [options.changeLogger] 45 | * @returns {Promise} 46 | */ 47 | this.pushToState = function (item, workflow, state, options) { 48 | return this._pushToState(item, workflow, state, options || {}); 49 | }; 50 | } 51 | 52 | module.exports = WorkflowProvider; 53 | -------------------------------------------------------------------------------- /core/period.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 25.10.16. 3 | */ 4 | 'use strict'; 5 | const moment = require('moment'); 6 | // jshint maxcomplexity: 20 7 | function add(parts, date) { 8 | var m = moment(date); 9 | for (var f in parts) { 10 | if (parts.hasOwnProperty(f)) { 11 | m = m.add(parts[f], f); 12 | } 13 | } 14 | return m.toDate(); 15 | } 16 | 17 | /** 18 | * @param {String} period 19 | * @returns {{fraction: Function, addTo: Function}} 20 | */ 21 | module.exports = function (period) { 22 | var parts = { 23 | y: 0, 24 | M: 0, 25 | w: 0, 26 | d: 0, 27 | h: 0, 28 | m: 0, 29 | s: 0 30 | }; 31 | var parser = /(\d+)\s*([yMwdhms])/g; 32 | var parsed = period.match(parser); 33 | while ((parsed = parser.exec(period)) !== null) { 34 | switch (parsed[2]) { 35 | case 'y': parts.y += parseInt(parsed[1]);break; 36 | case 'M': parts.M += parseInt(parsed[1]);break; 37 | case 'w': parts.w += parseInt(parsed[1]);break; 38 | case 'd': parts.d += parseInt(parsed[1]);break; 39 | case 'h': parts.h += parseInt(parsed[1]);break; 40 | case 'm': parts.m += parseInt(parsed[1]);break; 41 | case 's': parts.s += parseInt(parsed[1]);break; 42 | } 43 | } 44 | 45 | return { 46 | fraction: function (nm) { 47 | return parts[nm]; 48 | }, 49 | addTo: function (date) { 50 | return add(parts, date); 51 | } 52 | }; 53 | }; 54 | -------------------------------------------------------------------------------- /core/resolvePath.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 11/7/16. 3 | * @deprecated 4 | */ 5 | 'use strict'; 6 | module.exports = require('./system').toAbsolute; 7 | -------------------------------------------------------------------------------- /core/scope-alias.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 30.08.17. 3 | */ 4 | 'use strict'; 5 | const merge = require('merge'); 6 | 7 | /** 8 | * @param {{}} scope 9 | * @param {{}} aliases 10 | */ 11 | module.exports = function (scope, aliases) { 12 | if (!aliases) { 13 | return scope; 14 | } 15 | let result = merge({}, scope); 16 | for (let alias in aliases) { 17 | if (aliases.hasOwnProperty(alias)) { 18 | let nm = aliases[alias]; 19 | if (scope.hasOwnProperty(nm)) { 20 | result[alias] = scope[nm]; 21 | } 22 | } 23 | } 24 | return result; 25 | }; 26 | -------------------------------------------------------------------------------- /core/strToDate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by krasilneg on 22.02.17. 4 | */ 5 | const moment = require('moment'); 6 | 7 | module.exports = function (str, lang) { 8 | try { 9 | let dt; 10 | let offset = 0; 11 | if (lang) { 12 | dt = moment(str, 'L LT', lang, true); 13 | if (!dt.isValid()) { 14 | dt = moment(str, 'L', lang, true); 15 | } 16 | } 17 | if (!dt || !dt.isValid()) { 18 | dt = moment(str, moment.ISO_8601); 19 | if (dt.isValid()) { 20 | offset = moment.parseZone(str, moment.ISO_8601).utcOffset(); 21 | } 22 | } 23 | 24 | if (dt.isValid()) { 25 | dt = dt.toDate(); 26 | dt.utcOffset = offset; 27 | return dt; 28 | } 29 | } catch (err) { 30 | return null; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /core/system.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | 5 | module.exports.toAbsolute = function (pth) { 6 | if (!path.isAbsolute(pth)) { 7 | return path.normalize(path.join(__dirname, '..', pth)); 8 | } 9 | return pth; 10 | }; 11 | 12 | /** 13 | * @param {String} pth 14 | * @param {{}} params 15 | * @return {Promise} 16 | */ 17 | module.exports.readFile = function (pth, params) { 18 | return new Promise((resolve, reject) => { 19 | fs.readFile(pth, params, (err, file) => err ? reject(err) : resolve(file)); 20 | }); 21 | }; 22 | -------------------------------------------------------------------------------- /core/util/chain.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 24.01.17. 3 | */ 4 | 'use strict'; 5 | 6 | function applier(s, worker) { 7 | return function () { 8 | return worker(s); 9 | }; 10 | } 11 | 12 | module.exports = function (seq, worker) { 13 | var p = null; 14 | if (!Array.isArray(seq)) { 15 | seq = [seq]; 16 | } 17 | try { 18 | seq.forEach(function (s) { 19 | if (p) { 20 | p = p.then(applier(s, worker)); 21 | } else { 22 | p = applier(s, worker)(); 23 | } 24 | }); 25 | } catch (err) { 26 | return Promise.reject(err); 27 | } 28 | if (p) { 29 | return p; 30 | } 31 | return Promise.resolve(); 32 | }; 33 | -------------------------------------------------------------------------------- /core/util/dateOffset.js: -------------------------------------------------------------------------------- 1 | const DateTypes = require('core/DateTypes'); 2 | 3 | module.exports = function (date, mode) { 4 | if (date instanceof Date) { 5 | switch (mode) { 6 | case DateTypes.LOCALIZED: 7 | if (typeof date.utcOffset === 'undefined') { 8 | date.utcOffset = date.getTimezoneOffset(); 9 | } 10 | break; 11 | case DateTypes.UTC: { 12 | const offset = date.utcOffset || -date.getTimezoneOffset(); 13 | date.setUTCMinutes(date.getUTCMinutes() + offset); 14 | date.utcOffset = 0; 15 | } break; 16 | case DateTypes.REAL: 17 | default: 18 | if (typeof date.utcOffset !== 'undefined') { 19 | delete date.utcOffset; 20 | } 21 | } 22 | } 23 | return date; 24 | }; 25 | -------------------------------------------------------------------------------- /core/util/formula.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 26.07.18. 3 | */ 4 | 'use strict'; 5 | const Item = require('core/interfaces/DataRepository/lib/Item'); 6 | 7 | function getValue(context, nm) { 8 | if (context instanceof Item) { 9 | let p = context.property(nm); 10 | if (p) { 11 | return p.getValue(); 12 | } 13 | } 14 | 15 | if (nm.indexOf('.') > 0) { 16 | let v = getValue(context, nm.substring(0, nm.indexOf('.'))); 17 | if (v && typeof v === 'object') { 18 | v = getValue(v, nm.substring(nm.indexOf('.') + 1)); 19 | if (v !== null) { 20 | return v; 21 | } 22 | } 23 | } 24 | 25 | if (context.hasOwnProperty(nm)) { 26 | return context[nm]; 27 | } 28 | 29 | if (context.$context instanceof Item) { 30 | return getValue(context.$context, nm); 31 | } 32 | 33 | return null; 34 | } 35 | 36 | function parametrize(formula, context) { 37 | if (typeof formula === 'string' && formula.length > 1 && formula[0] === ':') { 38 | return getValue(context, formula.substr(1)); 39 | } else if (Array.isArray(formula)) { 40 | let result = []; 41 | formula.forEach((v) => { 42 | result.push(parametrize(v, context)); 43 | }); 44 | return result; 45 | } else if (formula && typeof formula === 'object') { 46 | let result = {}; 47 | for (let nm in formula) { 48 | result[nm] = parametrize(formula[nm], context); 49 | } 50 | return result; 51 | } 52 | return formula; 53 | } 54 | 55 | module.exports.parametrize = parametrize; 56 | -------------------------------------------------------------------------------- /core/util/recacher.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const recache = require('lib/util/recache'); 3 | 4 | /** 5 | * @param {{}} options 6 | * @param {String[]} options.classes 7 | * @param {MetaRepository} options.metaRepo 8 | * @param {DataRepository} options.dataRepo 9 | * @param {Boolean} options.skipDependencies 10 | * @param {Logger} options.log 11 | */ 12 | module.exports = function(options) { 13 | return recache( 14 | options.classes, 15 | {skipDependencies: options.skipDependencies, step: options.step}, 16 | options.metaRepo, 17 | options.dataRepo, 18 | msg => options.log.info(msg) 19 | ).catch((e) => { 20 | options.log.error(e); 21 | }); 22 | }; -------------------------------------------------------------------------------- /core/util/request.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | 3 | /** 4 | * @param {{}} reqParams 5 | * @returns {Promise.} 6 | */ 7 | module.exports = reqParams => new Promise( 8 | (resolve, reject) => { 9 | request(reqParams, (err, res, body) => err ? reject(err) : resolve(body)); 10 | } 11 | ); 12 | -------------------------------------------------------------------------------- /dispatcher/controllers/api/i18n.js: -------------------------------------------------------------------------------- 1 | const onError = require('../../../backend/error'); 2 | const respond = require('../../../backend/respond'); 3 | const strings = require('core/strings'); 4 | 5 | module.exports = (req, res) => respond(['auth'], (scope) => { 6 | try { 7 | const user = scope.auth.getUser(req); 8 | let base = strings.getBase('frontend'); 9 | 10 | let acceptedLanguages = user.language()? 11 | [user.language()] 12 | : []; 13 | acceptedLanguages = acceptedLanguages.concat( 14 | req.headers['accept-language'] 15 | .split(',') 16 | .map(lang => lang.split(';')[0]) 17 | ); 18 | let languageToUse; 19 | for (const language of acceptedLanguages) { 20 | if (app.locals.supportedLanguages.includes(language)) { 21 | languageToUse = language; 22 | break; 23 | } 24 | } 25 | 26 | res 27 | .set('Content-type', 'application/javascript') 28 | .send(Buffer.from(` 29 | 'use strict'; 30 | 31 | function I18nHandler() { 32 | this.base = {}; 33 | this.s = function(id, params) { 34 | if (id) { 35 | if (this.base.hasOwnProperty(id)) { 36 | var str = this.base[id]; 37 | if (params) { 38 | for (var p in params) { 39 | str = str.replace('%' + p, params[p]); 40 | } 41 | } 42 | return str; 43 | } 44 | return id; 45 | } 46 | return ''; 47 | }; 48 | } 49 | 50 | window.i18n = new I18nHandler(); 51 | window.s = window.__ = function (id, params) {return window.i18n.s(id, params);}; 52 | window.i18n.base = ${JSON.stringify(base(languageToUse))}; 53 | `)); 54 | } catch (err) { 55 | if (scope.logRecorder) { 56 | scope.logRecorder.stop(); 57 | } 58 | onError(scope, err, res, true); 59 | } 60 | }, 61 | res); 62 | -------------------------------------------------------------------------------- /dispatcher/controllers/api/markAllAsViewed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 06.02.18. 3 | */ 4 | 'use strict'; 5 | 6 | const onError = require('../../../backend/error'); 7 | const respond = require('../../../backend/respond'); 8 | 9 | // jshint maxstatements: 40, maxcomplexity: 20, maxdepth: 20, loopfunc: true 10 | 11 | module.exports = function (req, res) { 12 | respond(['auth', 'notifier'], 13 | /** 14 | * @param {{notifier: Notifier, auth: Auth}} scope 15 | * @param {AccessChecker} scope.accessChecker 16 | */ 17 | function (scope) { 18 | try { 19 | let user = scope.auth.getUser(req); 20 | scope.notifier.markAllAsRead(user.id()) 21 | .then(() => { 22 | res.send('Done'); 23 | }) 24 | .catch((err) => { 25 | onError(scope, err, res, true); 26 | }); 27 | } catch (err) { 28 | scope.logRecorder.stop(); 29 | onError(scope, err, res, true); 30 | } 31 | }, 32 | res 33 | ); 34 | }; -------------------------------------------------------------------------------- /dispatcher/controllers/api/markAsViewed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 06.02.18. 3 | */ 4 | 'use strict'; 5 | 6 | const onError = require('../../../backend/error'); 7 | const respond = require('../../../backend/respond'); 8 | 9 | // jshint maxstatements: 40, maxcomplexity: 20, maxdepth: 20, loopfunc: true 10 | 11 | 12 | module.exports = function (req, res) { 13 | respond(['auth', 'notifier'], 14 | /** 15 | * @param {{notifier: Notifier, auth: Auth}} scope 16 | * @param {AccessChecker} scope.accessChecker 17 | */ 18 | function (scope) { 19 | try { 20 | let user = scope.auth.getUser(req); 21 | scope.notifier.markAsRead(user.id(), req.params.id) 22 | .then(() => { 23 | res.send(req.params.id); 24 | }) 25 | .catch((err) => { 26 | onError(scope, err, res, true); 27 | }); 28 | } catch (err) { 29 | scope.logRecorder.stop(); 30 | onError(scope, err, res, true); 31 | } 32 | }, 33 | res 34 | ); 35 | }; -------------------------------------------------------------------------------- /dispatcher/controllers/api/moreViewedNotifications.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 06.02.18. 3 | */ 4 | 'use strict'; 5 | 6 | const onError = require('../../../backend/error'); 7 | const respond = require('../../../backend/respond'); 8 | 9 | // jshint maxstatements: 40, maxcomplexity: 20, maxdepth: 20, loopfunc: true 10 | 11 | module.exports = function (req, res) { 12 | respond(['auth', 'notifier'], 13 | /** 14 | * @param {{notifier: Notifier, auth: Auth}} scope 15 | * @param {AccessChecker} scope.accessChecker 16 | */ 17 | function (scope) { 18 | try { 19 | let user = scope.auth.getUser(req); 20 | let opts = { 21 | count: 10 + 1, // +1 - mark as having more 22 | viewed: true, 23 | offset: req.params.offset 24 | }; 25 | scope.notifier.list(user.id(), opts) 26 | .then((result) => { 27 | res.send(result); 28 | }) 29 | .catch((err) => { 30 | onError(scope, err, res, true); 31 | }); 32 | } catch (err) { 33 | scope.logRecorder.stop(); 34 | onError(scope, err, res, true); 35 | } 36 | }, 37 | res 38 | ); 39 | }; 40 | -------------------------------------------------------------------------------- /dispatcher/controllers/api/notifications.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kras on 06.02.18. 3 | */ 4 | 'use strict'; 5 | 6 | const onError = require('../../../backend/error'); 7 | const respond = require('../../../backend/respond'); 8 | 9 | // jshint maxstatements: 40, maxcomplexity: 20, maxdepth: 20, loopfunc: true 10 | 11 | 12 | module.exports = function (req, res) { 13 | respond(['auth', 'notifier'], 14 | /** 15 | * @param {{notifier: Notifier, auth: Auth}} scope 16 | * @param {AccessChecker} scope.accessChecker 17 | */ 18 | function (scope) { 19 | try { 20 | let user = scope.auth.getUser(req); 21 | let opts = {count: 100, new: true}; 22 | if (req.query.incremental) { 23 | opts.since = req.session.lnr; 24 | req.session.lnr = new Date(); 25 | } 26 | scope.notifier.list(user.id(), opts) 27 | .then((result) => { 28 | res.send(result); 29 | }) 30 | .catch((err) => { 31 | onError(scope, err, res, true); 32 | }); 33 | } catch (err) { 34 | scope.logRecorder.stop(); 35 | onError(scope, err, res, true); 36 | } 37 | }, 38 | res 39 | ); 40 | }; 41 | -------------------------------------------------------------------------------- /dispatcher/index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports.api = {}; 3 | module.exports.api.notifications = require('./controllers/api/notifications'); 4 | module.exports.api.markAsViewed = require('./controllers/api/markAsViewed'); 5 | module.exports.api.markAllAsViewed = require('./controllers/api/markAllAsViewed'); 6 | module.exports.api.moreViewedNotifications = require('./controllers/api/moreViewedNotifications'); 7 | module.exports.api.i18n = require('./controllers/api/i18n'); 8 | -------------------------------------------------------------------------------- /docs/en/2_system_description/functionality/notifications.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### Back: [Functionality](functionality.md) 4 | 5 | # Notifications 6 | 7 | **Notifications** - is displayed on the form as a red bell, when clicked, the notification tape (the last 10 unread) is displayed, when clicked on the notification, it disappears as read. The tape is updated every 15 seconds. If the bell is missing, this means that there are no new notifications. 8 | 9 | ## Setting the notifications 10 | 11 | The sending notifications to mail feature is implemented. Configure it in the project - **TODO**. 12 | 13 | The API for sending notifications programmatically is implemented. That means that you can send a notification in the event handler. 14 | 15 | In the admin when sending notifications the list of full user names (user @ local) separated by a space is indicates in the "Recipients" field. 16 | 17 | Notifications are stored in the following collections - ion_notification, ion_notification_recievers. 18 | 19 | 20 | -------------------------------------------------------------------------- 21 | 22 | 23 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/functionality/notifications.md)   24 |
iondv metrics
25 | 26 | 27 | 28 | -------------------------------------------------------------------------- 29 | 30 | Copyright (c) 2018 **LLC "ION DV"**. 31 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/functionality/virtual_attr.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### Back: [Functionality](functionality.md) 4 | 5 | # Virtual attributes 6 | 7 | ## Description 8 | 9 | Virtual attributes - a particular type of attributes, specified in the property attribute name, starting with `__`. The functional of each virtual attribute is different, and there are the following virtual attributes: 10 | 11 | - `__class` - displays the full code of the class in which the attribute was set. 12 | - `__classTitle` - displays the name of the class in which the attribute was set. 13 | 14 | -------------------------------------------------------------------------- 15 | 16 | 17 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/functionality/virtual_attr.md)   18 |
iondv metrics
19 | 20 | 21 | 22 | -------------------------------------------------------------------------- 23 | 24 | Copyright (c) 2018 **LLC "ION DV"**. 25 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_class/atr_indexed.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### The previous page: [Attribute types](property_types.md) 4 | 5 | # Attribute indexation 6 | 7 | **Attribute indexation** is required to accelerate the search. Indexation is set manually by assigning the value `true` for the `"indexed"` property, that is: 8 | 9 | ``` 10 | "indexed": true 11 | ``` 12 | 13 | Except for the following attribute types: 14 | 15 | 1. Indexation is set automatically (regardless of what is specified in the indexation field): 16 | 17 | * for key field 18 | 19 | * for objects with the `"compositeIndexes": True` field in the general part of the meta class 20 | 21 | 2. When importing a meta, all attribute objects of the reference type are indexed. 22 | 23 | 3. Objects of attributes of the "Collection" type are not indexed, because collections with back reference are not stored in an object, so indexing is not necessary. 24 | 25 | 26 | **NB:** The indexation of the attributes of the "Text" [1] and "HTML" [2] types is prohibited. Because the MongoDB has a limit on the size of the indexed value, and the size of the attribute values of these types may exceed the allowable size. 27 | 28 | ### The next page: [Autocompletion](atr_autoassigned.md) 29 | -------------------------------------------------------------------------- 30 | 31 | 32 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_class/atr_indexed.md)   33 |
iondv metrics
34 | 35 | 36 | 37 | -------------------------------------------------------------------------- 38 | 39 | Copyright (c) 2018 **LLC "ION DV"**. 40 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_class/journaling.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### The previous page: [Time and user tag of created objects and committed changes](time_user_tracker.md) 4 | 5 | # Journaling the changes 6 | 7 | **Journaling the changes** - indicates the need to log all actions performed on the object. Located in the `journaling` field of the main part of the meta class with two available values - `true` and `false`. A value of `true` indicates that you should log the changes. If the field is set to `false` or absent, then no object change logging is required. 8 | 9 | 10 | ## Example: 11 | 12 | ``` 13 | { 14 | "isStruct": false, 15 | "key": "okato", 16 | "semantic": "name", 17 | "name": "populatedArea", 18 | "caption": "Populated area", 19 | "journaling": true, 20 | "ancestor": null, 21 | "container": "", 22 | "creationTracker": "", 23 | "changeTracker": "", 24 | "properties": [] 25 | } 26 | ``` 27 | 28 | 29 | ### The next page: [Composite indexation](composite_indexes.md) 30 | -------------------------------------------------------------------------- 31 | 32 | 33 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_class/journaling.md)   34 |
iondv metrics
35 | 36 | 37 | 38 | -------------------------------------------------------------------------- 39 | 40 | Copyright (c) 2018 **LLC "ION DV"**. 41 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_class/key.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### The previous page: [Structure](isstruct.md) 4 | 5 | # The key attributes 6 | 7 | Each class should have a key attribute (the `" key "` field in the general part of the meta class). Without specified key attribute the application will not function correctly. 8 | 9 | ## Types of key fields 10 | 11 | 1. Guid - "Global identifier [12]". 12 | 2. "String [0]". 13 | 3. "Integer [6]". 14 | 15 | ## Key attribute requirements 16 | 17 | When creating the key attribute meta, set the `" unique "` and `"autoassigned"` fields to `true`. Disable the empty value by setting `" nullable "` to `false`. 18 | 19 | If the attribute is not automatically generated, then set the `"autoassigned"` field to `false`, so the field must be set by the operator when creating. 20 | 21 | ### The next page: [Semantic attributes](semantic.md) 22 | -------------------------------------------------------------------------- 23 | 24 | 25 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_class/key.md)   26 |
iondv metrics
27 | 28 | 29 | 30 | -------------------------------------------------------------------------- 31 | 32 | Copyright (c) 2018 **LLC "ION DV"**. 33 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_navigation/title.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### Back: [Meta node navigation](navigation_nodes.md) 4 | 5 | # Page title - `"title"` 6 | 7 | The **"title"** field is used to set the page title, different from the `"caption"` field in the navigation menu. 8 | 9 | ## Description 10 | 11 | When the page title is formed, firstly the system will use the value of the `"title"` field of the corresponding node navigation. If the `"title"` field is empty (not specified), the `caption` field of the meta navigation node is used to form the page title. When the page title is formed on the selection list pages, the system will use the `"caption"` field for the general part of the meta class. 12 | 13 | ## JSON 14 | 15 | ``` 16 | { 17 | "code": "administrations.municipals", 18 | "orderNumber": 0, 19 | "type": 1, 20 | "title": "Administrations of the municipal districts", \\ name should be different from the navigation node of the `"caption"` field 21 | "caption": "Municipal districts", 22 | "classname": "Organisation", 23 | "container": null, 24 | "collection": null, 25 | "url": null, 26 | "hint": "Administrations list of the municipal districts", 27 | "conditions": [], 28 | "sorting": [], 29 | } 30 | 31 | ``` 32 | -------------------------------------------------------------------------- 33 | 34 | 35 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_navigation/title.md)   36 |
iondv metrics
37 | 38 | 39 | 40 | -------------------------------------------------------------------------- 41 | 42 | Copyright (c) 2018 **LLC "ION DV"**. 43 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_view/create_edit_view.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/2_system_description/metadata_structure/meta_view/create_edit_view.md -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_view/field_sizes.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | ### Back: [Meta view - attribute part](meta_view_attribute.md) 3 | 4 | # Field sizes 5 | ``` 6 | 7 | module.exports = { 8 | TINY: 0, 9 | SHORT: 1, 10 | MEDIUM: 2, 11 | LONG: 3, 12 | BIG: 4 13 | }; 14 | ``` 15 | -------------------------------------------------------------------------- 16 | 17 | 18 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_view/field_sizes.md)   19 |
iondv metrics
20 | 21 | 22 | 23 | -------------------------------------------------------------------------- 24 | 25 | Copyright (c) 2018 **LLC "ION DV"**. 26 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_view/fields.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### The previous page: [Masks](mask.md) 4 | 5 | # Fields 6 | 7 | ## Description 8 | 9 | **Fields** - contains class attributes that are combined, on any ground, into a group (for more details see [Type "Group [0]")](type_group.md). 10 | 11 | **Attention:** this property applies only to the attribute type - "Group [0]". 12 | 13 | ### Example: 14 | 15 | **NB:** On the form, the specified attributes are displayed on the lower level of the hierarchy, on the top is the name of the group. 16 | 17 | ``` 18 | { 19 | "tabs": [ 20 | { 21 | "caption": "", 22 | "fullFields": [ 23 | { 24 | "caption": "nameGroup", 25 | "type": 0, 26 | "property": "", 27 | "size": 2, 28 | "maskName": null, 29 | "mask": null, 30 | "mode": null, 31 | "fields": [ 32 | { 33 | "caption": "atr1", 34 | "type": 1, 35 | ... 36 | }, 37 | { 38 | "caption": "atr2", 39 | "type": 1, 40 | ... 41 | } 42 | ] 43 | } 44 | ], 45 | "shortFields": [] 46 | } 47 | ] 48 | } 49 | 50 | 51 | ``` 52 | 53 | ### The next page: [Commands](commands.md) 54 | 55 | -------------------------------------------------------------------------- 56 | 57 | 58 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_view/fields.md)   59 |
iondv metrics
60 | 61 | 62 | 63 | -------------------------------------------------------------------------- 64 | 65 | Copyright (c) 2018 **LLC "ION DV"**. 66 | All rights reserved. 67 | -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_view/list_view.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/2_system_description/metadata_structure/meta_view/list_view.md -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_view/overridemode.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### Back: [Meta view - general part](meta_view_main.md) 4 | 5 | # Override Mode 6 | 7 | The **Override Mode** field - `"overrideMode"` allows to set two types of the Override Mode - `"Overlap"` and `"Override"`. 8 | 9 | Types of the Override Mode in the meta view: 10 | 11 | **Type 1** - `"Override"` - overrides the standard display mode of the corresponding attributes specified in the meta view of the class. Attributes that are not specified in the meta view of the class are displayed in a standard mode on the form according to the specified default order. 12 | 13 | **Type 2** - `"Overlap"` - only attributes specified in the meta view are displayed. 14 | 15 | ### Example 16 | 17 | ``` 18 | "actions": null, 19 | "siblingFixBy": null, 20 | "siblingNavigateBy": null, 21 | "historyDisplayMode": 0, 22 | "collectionFilters": null, 23 | "version": null, 24 | "overrideMode": 1, 25 | "commands": [ 26 | 27 | ``` 28 | -------------------------------------------------------------------------- 29 | 30 | 31 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_view/overridemode.md)   32 |
iondv metrics
33 | 34 | 35 | 36 | -------------------------------------------------------------------------- 37 | 38 | Copyright (c) 2018 **LLC "ION DV"**. 39 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_view/styles.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### Back: [Meta view - general part](meta_view_main.md) 4 | 5 | # Highlighting lines in the list 6 | 7 | Conditions of **highlighting** the lines in the list are specified with the formula. 8 | 9 | A list of supported formulas can be found [here](/docs/en/2_system_description/metadata_structure/meta_class/atr_formula.md). 10 | You can configure it in the General part of the list meta view as follows: 11 | 12 | ``` 13 | "styles": { 14 | "css-class": "formula" 15 | } 16 | ``` 17 | 18 | where the `"css-class"` - is a class of available design themes and the `"formula"` - is a formula with a condition for highlighting the strings in the list. 19 | 20 | ### Available themes of the `"css-class"` design 21 | 22 | * `attention-1` - red 23 | * `attention-2` - yellow 24 | * `attention-3` - orange 25 | * `attention-4` - gray 26 | * `attention-5` - blue 27 | * `attention-6` - green 28 | 29 | ## Purpose of use 30 | 31 | When you open the view list of objects, the strings of the table are highlighted according to the conditions of the formula and the theme class. 32 | 33 | ### Example 34 | 35 | ```json 36 | "styles": { 37 | "attention-1": "lt($real, 0)" 38 | }, 39 | ``` 40 | 41 | `$real` - any integer. If $real - less than 0, then the column is highlighted in red. 42 | 43 | -------------------------------------------------------------------------- 44 | 45 | 46 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_view/styles.md)   47 |
iondv metrics
48 | 49 | 50 | 51 | -------------------------------------------------------------------------- 52 | 53 | Copyright (c) 2018 **LLC "ION DV"**. 54 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/metadata_structure/meta_workflows/status_wf.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### The previous page: [Meta workflows](meta_workflows.md) 4 | 5 | # Workflow statuses 6 | 7 | ### JSON 8 | 9 | ``` 10 | "states": [ 11 | { 12 | "name": "new", 13 | "caption": "New", 14 | "maxPeriod": null, 15 | "conditions": [], 16 | "itemPermissions": [], 17 | "propertyPermissions": [], 18 | "selectionProviders": [] 19 | } 20 | ] 21 | 22 | ``` 23 | ## Field description 24 | 25 | | Field | Description | 26 | |:-----|:-----------| 27 | |`"name"`| Status system name.| 28 | |`"caption"`| Status logical name.| 29 | |`"maxPeriod"`| _no data_ | 30 | |`"conditions"`| Conditions for workflow status. Set in the same way as the "Conditions for the selection of valid values".| 31 | |`"itemPermissions"`| Permissions for an object. | 32 | |`"propertyPermissions"`| Permissions for properties. | 33 | |`"selectionProviders"`| Selection list of valid values. | 34 | 35 | 36 | ### The next page: [Workflow transitions](transitions_wf.md) 37 | 38 | -------------------------------------------------------------------------- 39 | 40 | 41 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/metadata_structure/meta_workflows/status_wf.md)   42 | 43 | -------------------------------------------------------------------------- 44 | 45 | Copyright (c) 2018 **LLC "ION DV"**. 46 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/2_system_description/platform_configuration/deploy.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### The previous page: [Meta report](/docs/en/2_system_description/metadata_structure/meta_report/meta_report.md) 4 | 5 | # Configuration file - `deploy.json` 6 | 7 | **Configuration file - deploy.json** - is a file that describes the structure of the parameters of the software system and its specific configuration. 8 | 9 | ## Structure of the deploy.json file: 10 | 11 | | Field | Name | Description | 12 | |:-------------|:--------|:-------------| 13 | | `"namespace":` | **Project name** | The project namespace. | 14 | | `"parametrised": true,`| **Parameterization** | The parameterization settings. Set the "true" value to spesify the parameters to which, the system transfers the variables defined in ini-files or variables of the project environment when building the application. | 15 | | `"globals": {` | [**Global settings**](deploy_globals.md) | Global configuration settings. | 16 | | `"deployer": "built-in"` | **Builds** | The built configuration parameter. Currently, it is the only one. | 17 | | `"modules"` | [**Modules settings**](deploy_modules.md) | Module configuration settings. | 18 | 19 | ## The [full example](deploy_ex.md) of the "deploy.json" file 20 | 21 | ### The next page: [Dependencies in package.json](package.md) 22 | 23 | -------------------------------------------------------------------------- 24 | 25 | 26 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/2_system_description/platform_configuration/deploy.md)   27 | 28 | -------------------------------------------------------------------------- 29 | 30 | Copyright (c) 2018 **LLC "ION DV"**. 31 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/3_modules_description/account.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### Back: [Modules](modules.md) 4 | 5 | ## The Personal account module 6 | 7 | **Personal account** (PA) - is used to display various "instrumental" forms, i.e. in the applications, we set up the navigation (or the page-forms), the module reads these data and forms the navigation and the display of these pages. 8 | 9 | ### Module configuration 10 | 11 | 1. Put the html-page in the application in a certain directory . 12 | 2. Write this directory in deploy.json in the module settings, and optionally a hash array of a match between the file name and the display name. 13 | 3. The personal account reads these settings and displays the PA navigation menu in the master template. 14 | 4. By clicking on the menu item in the working area of the PA window, the corresponding markup from the html file is displayed. 15 | 5. Also in deploy.json file, in the settings of the PA module, the tool page is specified by default. If not specified, the first in order is taken. 16 | 17 | There is also the possibility of structuring the menu by nesting directories. 18 | 19 | -------------------------------------------------------------------------- 20 | 21 | 22 | #### [Licence](/LICENSE)  [Contact us](https://iondv.com/portal/contacts)   [English](account.md)   23 |
iondv metrics
24 | 25 | 26 | 27 | -------------------------------------------------------------------------- 28 | 29 | Copyright (c) 2018 **LLC "ION DV".** 30 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/3_modules_description/modules.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### The previous page: [Functionality](/docs/en/2_system_description/functionality/functionality.md) 4 | 5 | # Modules 6 | 7 | **Modules** - are independent blocks with mandatory or additional functionality, whose structure is subject to certain rules. 8 | 9 | | Name | Description | 10 | |:---------:|:---------| 11 | |[**Registry**](registry.md) | A central module designed specifically for working with data based on metadata structures. | 12 | |[**Report**](report.md) | A module designed for the formation of analytical reports. | 13 | |[**Gantt-chart**](gantt_chart.md) | A module designed to display hierarchical data with dates. | 14 | |[**Portal**](portal.md) | A module for displaying arbitrary data templates. | 15 | |[**Dashboard**](dashboards.md) | A module designed to display brief information in the form of blocks. | 16 | |[**Ionadmin**](admin.md) | A module for assigning rights. | 17 | |[**Account**](account.md)| A personal account module that forms the display logic. | 18 | |[**Soap**](soap.md) | A module of requests to services.| 19 | -------------------------------------------------------------------------- 20 | 21 | 22 | #### [Licence](/LICENSE)  [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/3_modules_description/modules.md)   23 |
iondv metrics
24 | 25 | 26 | 27 | -------------------------------------------------------------------------- 28 | 29 | Copyright (c) 2018 **LLC "ION DV".** 30 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/3_modules_description/registry.md: -------------------------------------------------------------------------------- 1 | #### [Content](/docs/en/index.md) 2 | 3 | ### Back: [Modules](modules.md) 4 | 5 | # The "Registry" module 6 | 7 | **The registry module** – is a central module designed specifically for working with data based on metadata structures - including project management, programs, events, etc. 8 | 9 | ## Setting 10 | 11 | * [DI (treegridController)](registry_treegrid.md) 12 | 13 | ## Deploy 14 | 15 | ### Configure polling frequency in deploy.json 16 | 17 | Setting the frequency of polling the server to check that the objects is not blicked in deploy.json: 18 | 19 | ``` 20 | "registry": { 21 | "globals": { 22 | "notificationCheckInterval": 60000 // once in a minute 23 | } 24 | } 25 | ``` 26 | 27 | ### Setting "createByCopy" 28 | 29 | Setting to display the "Create more" button in deploy.json: 30 | 31 | ``` 32 | "createByCopy": [ 33 | "person@khv-childzem" // class 34 | ], 35 | ``` 36 | 37 | ## Filters 38 | 39 | For more information on the filters see [here](/docs/en/2_system_description/functionality/filter.md). 40 | 41 | ### Setting "help" on filters 42 | 43 | "Help" is placed in the template file - `modules/registry/view/default/templates/view/list-filter-helper.ejs` 44 | 45 | ## Code requirements 46 | 47 | Frontend component writing style is [here](registry_code.md) 48 | 49 | -------------------------------------------------------------------------- 50 | 51 | 52 | #### [Licence](/LICENSE)  [Contact us](https://iondv.com/portal/contacts)   [Russian](/docs/ru/3_modules_description/registry.md)   53 |
iondv metrics
54 | 55 | 56 | 57 | -------------------------------------------------------------------------- 58 | 59 | Copyright (c) 2018 **LLC "ION DV".** 60 | All rights reserved. -------------------------------------------------------------------------------- /docs/en/images/ION_logo_black_mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/images/ION_logo_black_mini.png -------------------------------------------------------------------------------- /docs/en/images/Insta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/images/Insta.png -------------------------------------------------------------------------------- /docs/en/images/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/images/facebook.png -------------------------------------------------------------------------------- /docs/en/images/iondv_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/images/iondv_logo.png -------------------------------------------------------------------------------- /docs/en/images/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/images/linkedin.png -------------------------------------------------------------------------------- /docs/en/images/schema_en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/images/schema_en.png -------------------------------------------------------------------------------- /docs/en/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/en/images/twitter.png -------------------------------------------------------------------------------- /docs/ru/2_system_description/functionality/notifications.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Назад: [Функциональность](functionality.md) 4 | 5 | # Уведомления 6 | 7 | **Уведомления** - на форме отображются в виде красного колокольчика, при клике на котором отображается лента уведомлений (10 последних непрочитанных), при клике на уведомлении оно скрывается как прочитанное. Лента обновляется раз в 15 секунд. Если колокольчик отсутсвует это значит что уведомлений нет. 8 | 9 | ## Настройка уведомлений 10 | 11 | Реализована отправка уведомлений на почту. Настраивается в проекте - **TODO**. 12 | 13 | Реализовано API для отправки уведомлений программно. т.е. можно в обработчике события отправить уведомление. 14 | В админке при отправке уведомлений в поле "Получатели" указывается список полных имен пользователей (user@local) разделенных пробелом. 15 | 16 | Хранение уведомлений происходит в коллекциях: ion_notification, ion_notification_recievers. 17 | 18 | 19 | -------------------------------------------------------------------------- 20 | 21 | 22 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/functionality/printed_forms.md)   23 |
iondv metrics
24 | 25 | 26 | 27 | -------------------------------------------------------------------------- 28 | 29 | Copyright (c) 2018 **LLC "ION DV"**. 30 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/functionality/virtual_attr.md: -------------------------------------------------------------------------------- 1 | #### [Содержание](/docs/ru/index.md) 2 | 3 | ### Назад: [Функциональность](functionality.md) 4 | 5 | # Виртуальные атрибуты 6 | 7 | ## Описание 8 | 9 | Виртуальные атрибуты - специальный тип атрибутов, указывается в `property` наименование атрибута, начинающееся с `__`. Функционал каждого виртуального атрибута различен, существуют следующие виртуальные атрибуты: 10 | 11 | - `__class` - выводит полный код класса, в котором заведен атрибут 12 | - `__classTitle` - выводит наименование класса, в котором заведен атрибут 13 | 14 | -------------------------------------------------------------------------- 15 | 16 | 17 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/functionality/virtual_attr.md)   18 |
iondv metrics
19 | 20 | 21 | 22 | -------------------------------------------------------------------------- 23 | 24 | Copyright (c) 2018 **LLC "ION DV"**. 25 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_class/atr_indexed.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Предыдущая страница: [Типы атрибутов](property_types.md) 4 | 5 | # Индексация атрибутов 6 | 7 | **Индексация** атрибутов необходима для ускорения поиска. Индексация задается вручную, присвоением значения `true` для свойства `"indexed"`, то есть: 8 | 9 | ``` 10 | "indexed": true 11 | ``` 12 | 13 | За исключением следующих типов атрибутов: 14 | 15 | 1. Индексация задается автоматически (независимо от того, что указано в индексации для поля): 16 | 17 | * для ключевого поля 18 | 19 | * для объектов с полем `"compositeIndexes": true` в основной части меты класса 20 | 21 | 2. При импорте меты принудительно индексируются все объекты атрибутов типа "Ссылка". 22 | 23 | 3. Объекты атрибутов типа "Коллекция" не индексируются, так как коллекции с обратной ссылкой не хранятся в объекте, соответственно в индексации нет необходимости. 24 | 25 | ``` 26 | NB. Запрещается индексация атрибутов типа "Текст" [1] и "HTML" [2]. 27 | Связано с ограничением MongoDB на размер индексируемого значения, 28 | т.к. размер значения атрибутов данных типов может превышать допустимый размер. 29 | ``` 30 | ### Следующая страница: [Автозаполнение](atr_autoassigned.md) 31 | -------------------------------------------------------------------------- 32 | 33 | 34 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_class/atr_indexed.md)   35 |
iondv metrics
36 | 37 | 38 | 39 | -------------------------------------------------------------------------- 40 | 41 | Copyright (c) 2018 **LLC "ION DV"**. 42 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_class/journaling.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Предыдущая страница: [Метка времени и пользователя создания и изменения](time_user_tracker.md) 4 | 5 | # Журналирование 6 | 7 | **Журналирование** - указывает на необходимость журналирования всех действий произведенных над объектом. Находится в поле `journaling` основной части меты класса. Значение `true` указывает на необходимость журналирования. Если в поле указано значение `false` или отсутсвует, то журналирование изменений объекта не требуется. 8 | 9 | ## Пример: 10 | 11 | ``` 12 | { 13 | "isStruct": false, 14 | "key": "okato", 15 | "semantic": "name", 16 | "name": "naselenniyPunkt", 17 | "caption": "Населенный пункт", 18 | "journaling": true, 19 | "ancestor": null, 20 | "container": "", 21 | "creationTracker": "", 22 | "changeTracker": "", 23 | "properties": [] 24 | } 25 | ``` 26 | 27 | 28 | ### Следующая страница: [Индексация](composite_indexes.md) 29 | -------------------------------------------------------------------------- 30 | 31 | 32 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_class/journaling.md)   33 |
iondv metrics
34 | 35 | 36 | 37 | -------------------------------------------------------------------------- 38 | 39 | Copyright (c) 2018 **LLC "ION DV"**. 40 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_class/key.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Предыдущая страница: [Структура](isstruct.md) 4 | 5 | # Ключевые поля 6 | В каждом классе обязательно должен быть задан ключевой атрибут (поле `"key"` основной части меты класса). Без этого приложение не будет функционировать. 7 | 8 | ## Типы ключевых полей 9 | 10 | 1. Guid - "Глобальный идентификатор [12]". 11 | 2. "Строка [0]". 12 | 3. "Целое [6]". 13 | 14 | ## Требования к ключевому атрибуту 15 | 16 | При формировании меты ключевого атрибута, поля `"unique"` и `"autoassigned"` выставляются в `true`. Необходимо запретить пустое значение, выставляя `"nullable"` в `false`. 17 | 18 | Если атрибут не генерируется автоматически, то `"autoassigned"` можно поставить в `false`, тогда поле должно быть задано оператором при создании. Например если это код классификатора или регистрационный номер задаваемый внешним способом (на бумаге). 19 | 20 | ### Следующая страница: [Семантический атрибут](semantic.md) 21 | -------------------------------------------------------------------------- 22 | 23 | 24 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_class/key.md)   25 |
iondv metrics
26 | 27 | 28 | 29 | -------------------------------------------------------------------------- 30 | 31 | Copyright (c) 2018 **LLC "ION DV"**. 32 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_class/type_collection14.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Предыдущая страница: [Ссылка](type_reference13.md) 4 | 5 | # Коллекция 6 | 7 | ## Общее описание 8 | 9 | **Коллекция** - тип данных, позволяющий выводить в объекте списки других объектов. Данные объекты могут быть объектами любого класса включая исходный. 10 | 11 | 12 | 13 | ## Способы задания коллекций с точки зрения используемых полей атрибутивной части меты классов: 14 | 1. `один-ко-многим` - означает наличие контейнера и вложенного объекта с ссылкой на контейнер. В контейнере необходимо указать коллекцию, а у нее указать ссылочный атрибут вложенного объекта по которому формируется связь. __См. Обратные ссылки в контексте коллекций.__ 15 | 2. `многие-ко-многим` - необходимо определить коллекцию без ссылок, и указать класс вложенных элементов - связи создаются при помещении в коллекцию и хранятся как отдельные сущности в БД. __См. Коллекции.__ 16 | 3. `обратная коллекция` - если коллекция многие ко многим задается на основании коллекции в другом объекте. то другая сторона связи задается через *backColl*. __См. Обратные коллекции.__ 17 | 18 | См. полное описание типа `Коллекция` в атрибутивной части меты класса - [**Атрибут коллекции и обратной коллекции**](atr_itemclass_backcoll.md). 19 | 20 | 21 | 22 | ### Следующая страница: [Структура](type_isstruct16.md) 23 | -------------------------------------------------------------------------- 24 | 25 | 26 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_class/type_collection14.md)   27 |
iondv metrics
28 | 29 | 30 | 31 | -------------------------------------------------------------------------- 32 | 33 | Copyright (c) 2018 **LLC "ION DV"**. 34 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_navigation/title.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Назад: [Мета узлов навигации](navigation_nodes.md) 4 | 5 | # Заголовок страницы - `"title"` 6 | 7 | Поле **"title"** необходимо для того, чтобы задать отличный от поля `"caption"` заголовок страницы в меню навигации. 8 | 9 | ## Описание 10 | 11 | Для формирования заголовка страницы в первую очередь используется значение поля `"title"` соответствующего узла навигации. Если поле `"title"` не задано - пустая строка, то для формирования заголовка страницы используется поле `"caption"` меты узла навигации. 12 | Для формирования заголовка страницы на страницах списка выбора (при открытии списка класса справочника из форм) используется `"caption"` общей части меты класса. 13 | 14 | ## JSON 15 | 16 | ``` 17 | { 18 | "code": "administrations.municipals", 19 | "orderNumber": 0, 20 | "type": 1, 21 | "title": "Администрации муниципальных районов", \\ отличается от наименования узла навигации поля `"caption"` 22 | "caption": "Муниципальные районы", 23 | "classname": "Organisation", 24 | "container": null, 25 | "collection": null, 26 | "url": null, 27 | "hint": "Список администраций муниципальных районов", 28 | "conditions": [], 29 | "sorting": [], 30 | } 31 | 32 | ``` 33 | -------------------------------------------------------------------------- 34 | 35 | 36 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_navigation/title.md)   37 |
iondv metrics
38 | 39 | 40 | 41 | -------------------------------------------------------------------------- 42 | 43 | Copyright (c) 2018 **LLC "ION DV"**. 44 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_view/create_edit_view.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/2_system_description/metadata_structure/meta_view/create_edit_view.md -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_view/field_sizes.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | ### Назад: [Мета представлений - атрибутивная часть](meta_view_attribute.md) 3 | 4 | # Размеры полей 5 | ``` 6 | 7 | module.exports = { 8 | TINY: 0, 9 | SHORT: 1, 10 | MEDIUM: 2, 11 | LONG: 3, 12 | BIG: 4 13 | }; 14 | ``` 15 | -------------------------------------------------------------------------- 16 | 17 | 18 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_view/field_sizes.md)   19 |
iondv metrics
20 | 21 | 22 | 23 | -------------------------------------------------------------------------- 24 | 25 | Copyright (c) 2018 **LLC "ION DV"**. 26 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_view/list_view.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/2_system_description/metadata_structure/meta_view/list_view.md -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_view/overridemode.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Назад: [Мета представлений - общая часть](meta_view_main.md) 4 | 5 | # Режим наложения 6 | 7 | Поле **Режим наложения** - `"overrideMode"` позволяет задать два значения `"Перекрыть"` и `"Переопределить"`. 8 | 9 | Настройка режимов наложения в мете представления: 10 | 11 | **Тип 1** - `"Переопределить"` - переопределяет стандартный способ отображения соответствующих атрибутов заданных в мете представления класса. Атрибуты, которые не заданы в мете представления класса, отображаются стандартным образом на форме согласно заданной очередности по умолчанию. 12 | 13 | **Тип 2** - `"Перекрыть"` - выводятся только атрибуты заданные в мете представления. 14 | 15 | ### Пример 16 | 17 | ``` 18 | "actions": null, 19 | "siblingFixBy": null, 20 | "siblingNavigateBy": null, 21 | "historyDisplayMode": 0, 22 | "collectionFilters": null, 23 | "version": null, 24 | "overrideMode": 1, 25 | "commands": [ 26 | 27 | ``` 28 | -------------------------------------------------------------------------- 29 | 30 | 31 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_view/overridemode.md)   32 |
iondv metrics
33 | 34 | 35 | 36 | -------------------------------------------------------------------------- 37 | 38 | Copyright (c) 2018 **LLC "ION DV"**. 39 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_view/styles.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Назад: [Мета представлений - общая часть](meta_view_main.md) 4 | 5 | # Выделение цветом строк в списке 6 | 7 | Условия **выделение цветом** строк в списке задаются с помощью формулы. 8 | 9 | Список поддерживаемых функций можно посмотреть [здесь](/docs/ru/2_system_description/metadata_structure/meta_class/atr_formula.md). Настройка задается в общей части меты представления списка и выглядит следующим образом: 10 | 11 | ``` 12 | "styles": { 13 | "css-class": "формула" 14 | } 15 | ``` 16 | 17 | где, `"css-class"` - класс доступных тем оформления, а `"формула"` - формула с условием для применения выделения цветом строк в списке. 18 | 19 | #### Доступные темы оформления `"css-class"` 20 | 21 | * `attention-1` - red 22 | * `attention-2` - yellow 23 | * `attention-3` - orange 24 | * `attention-4` - gray 25 | * `attention-5` - blue 26 | * `attention-6` - green 27 | 28 | #### Назначение 29 | 30 | При открытии формы представления списка объектов, в соответствии с условиями формулы и класса темы оформления - строки таблицы выделяются цветом. 31 | 32 | #### Пример 33 | 34 | ```json 35 | "styles": { 36 | "attention-1": "lt($real, 0)" 37 | }, 38 | ``` 39 | 40 | `$real` - любое целое число. Если $real - меньше 0, то столбец выделяется красным цветом. 41 | 42 | -------------------------------------------------------------------------- 43 | 44 | 45 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_view/styles.md)   46 |
iondv metrics
47 | 48 | 49 | 50 | -------------------------------------------------------------------------- 51 | 52 | Copyright (c) 2018 **LLC "ION DV"**. 53 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/metadata_structure/meta_workflows/status_wf.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Предыдущая страница: [Мета бизнес-процесса](meta_workflows.md) 4 | 5 | # Статусы бизнес-процесса 6 | 7 | ### JSON 8 | 9 | ``` 10 | "states": [ 11 | { 12 | "name": "new", 13 | "caption": "Новое", 14 | "maxPeriod": null, 15 | "conditions": [], 16 | "itemPermissions": [], 17 | "propertyPermissions": [], 18 | "selectionProviders": [] 19 | } 20 | ] 21 | 22 | ``` 23 | ## Описание полей 24 | 25 | | Поле |Описание | 26 | |:-----|:-----------| 27 | |`"name"`| Системное имя статуса| 28 | |`"caption"`| Логическое имя статуса| 29 | |`"maxPeriod"`| _нет данных_ | 30 | |`"conditions"`| Условия для статуса БП. Задаются аналогично "Условиям отбора допустимых значений". | 31 | |`"itemPermissions"`| Разрешения для объекта | 32 | |`"propertyPermissions"`| Разрешения для свойств | 33 | |`"selectionProviders"`| Выборка допустимых значений 34 | 35 | 36 | ### Следующая страница: [Переходы бизнес-процесса](transitions_wf.md) 37 | 38 | -------------------------------------------------------------------------- 39 | 40 | 41 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/metadata_structure/meta_workflows/status_wf.md)   42 |
iondv metrics
43 | 44 | -------------------------------------------------------------------------- 45 | 46 | Copyright (c) 2018 **LLC "ION DV"**. 47 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/2_system_description/platform_configuration/deploy.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Предыдущая страница: [Мета отчёта](/docs/ru/2_system_description/metadata_structure/meta_report/meta_report.md) 4 | 5 | # Конфигурационный файл - `deploy.json` 6 | 7 | **Конфигурационный файл deploy.json** - это файл, в котором описывается структура параметров программной системы и её конкретная настройка. 8 | 9 | ## Структура файла deploy.json: 10 | 11 | | Поле | Имя | Описание | 12 | |:-------------|:--------|:-------------| 13 | | `"namespace":` | **Название проекта** | Пространство имен проекта. | 14 | | `"parametrised": true,`| **Параметризация** | Подключение параметризации. При установленном значении "true" есть возможность задавать параметры, в которые, при сборке приложения, передаются переменные, заданные в ini-файлах или переменных окружения проекта. | 15 | | `"globals": {` | [**Глобальные настройки**](deploy_globals.md) | Глобальные параметры конфигурирования. | 16 | | `"deployer": "built-in"` | **Сборки** | Параметр конфигурирования сборки, на данный момент единственный. | 17 | | `"modules"` | [**Настройки модулей**](deploy_modules.md) | Массив объектов - описание модулей. | 18 | 19 | ### Пример файла [deploy.json](deploy_ex.md) 20 | 21 | ### Следующая страница: [Зависимости в package.json](package.md) 22 | 23 | -------------------------------------------------------------------------- 24 | 25 | 26 | #### [Licence](/LICENSE)   [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/2_system_description/platform_configuration/deploy.md)   27 |
iondv metrics
28 | 29 | -------------------------------------------------------------------------- 30 | 31 | Copyright (c) 2018 **LLC "ION DV"**. 32 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/3_modules_description/account.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Назад: [Модули](modules.md) 4 | 5 | ## Личный кабинет 6 | 7 | **Личный кабинет**- нужен для отображения различных "инструментальных" форм, т.е. в приложениях мы заводим навигацию (или сами формы-страницы), модуль считывает их, формирует на основании них навигацию, и логику отображения этих страниц. 8 | 9 | ### Настройка модуля 10 | 11 | 1. В приложении в некую директорию кладем html-страницы. 12 | 2. В deploy.json в настройках модуля ЛК прописываем эту директорию, а также опционально хеш-массив соответствия между именем файла и отображаемым названием. 13 | 3. ЛК считывает эти настройки и в мастер-шаблоне отображает меню навигации ЛК. 14 | 4. По клику на пункте меню в рабочей области окна ЛК отображается соответствующая разметка из html-файла. 15 | 5. Также в deploy.json в настройках модуля ЛК указывается страница-инструмент по умолчанию, если не указан берется первый считанный по порядку. 16 | 17 | Также есть возможность структурирования меню посредством вложенности директорий. 18 | 19 | -------------------------------------------------------------------------- 20 | 21 | 22 | #### [Licence](/LICENSE)  [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/3_modules_description/account.md)   23 |
iondv metrics
24 | 25 | 26 | 27 | -------------------------------------------------------------------------- 28 | 29 | Copyright (c) 2018 **LLC "ION DV".** 30 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/3_modules_description/modules.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Предыдущая страница: [Функциональность приложения](/docs/ru/2_system_description/functionality/functionality.md) 4 | 5 | # Модули 6 | 7 | **Модули** - это независимые блоки с обязательной или дополнительной функциональностью, чья структура подчиняется определенным правилам. 8 | 9 | | Наименование | Описание | 10 | |:---------:|:---------| 11 | |[**Registry**](registry.md) | Ключевой модуль предназначенный непосредственно для работы с данными на основе структур метаданных. | 12 | |[**Report**](report.md) | Модуль предназначенный для формирования аналитических отчетов. | 13 | |[**Gantt-chart**](gantt_chart.md) | Модуль для вывода данных с датами. | 14 | |[**Portal**](portal.md) | Модуль для вывода произвольных шаблонов данных. | 15 | |[**Dashboard**](dashboards.md) | Модуль предназначенный для выведения краткой информации в виде блоков. | 16 | |[**Ionadmin**](admin.md) | Модуль администрирования для назначения прав. | 17 | |[**Account**](account.md)| Модуль личного кабинета который формирует логику отображения. | 18 | |[**Soap**](soap.md) | Модуль запросов к сервисам.| 19 | -------------------------------------------------------------------------- 20 | 21 | 22 | #### [Licence](/LICENSE)  [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/3_modules_description/modules.md)   23 |
iondv metrics
24 | 25 | 26 | 27 | -------------------------------------------------------------------------- 28 | 29 | Copyright (c) 2018 **LLC "ION DV".** 30 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/3_modules_description/registry.md: -------------------------------------------------------------------------------- 1 | #### [Оглавление](/docs/ru/index.md) 2 | 3 | ### Назад: [Модули](modules.md) 4 | 5 | # Модуль "Registry" 6 | 7 | **Модуль регистра (registry)** – ключевой модуль предназначенный непосредственно для работы с данными на основе структур метаданных – в том числе по ведению проектов, программ, мероприятий и др. 8 | 9 | ## Настройка 10 | 11 | * [DI (treegridController)](registry_treegrid.md) 12 | 13 | ### Deploy 14 | 15 | ### Настройка частоты опроса в deploy.json 16 | 17 | Настройка частоты опроса сервера, что объект не заблокирован в deploy.json: 18 | 19 | ``` 20 | "registry": { 21 | "globals": { 22 | "notificationCheckInterval": 60000 // раз в минуту 23 | } 24 | } 25 | ``` 26 | 27 | ### Настройка createByCopy 28 | 29 | Настройка отображения кнопки "Создать еще" в deploy.json: 30 | 31 | ``` 32 | "createByCopy": [ 33 | "person@khv-childzem" // класс 34 | ], 35 | ``` 36 | 37 | ## Фильтры 38 | 39 | Подробнее о фильтрах [здесь](/docs/ru/2_system_description/functionality/filter.md). 40 | 41 | ### Настройка помощь по фильтрам 42 | 43 | Справка размещается в файле шаблона `modules/registry/view/default/templates/view/list-filter-helper.ejs` 44 | 45 | ## Требования к коду 46 | 47 | Cтиль написания компонентов фронт-енда [здесь](registry_code.md) 48 | 49 | -------------------------------------------------------------------------- 50 | 51 | 52 | #### [Licence](/LICENSE)  [Contact us](https://iondv.com/portal/contacts)   [English](/docs/en/3_modules_description/registry.md)   53 |
iondv metrics
54 | 55 | 56 | 57 | -------------------------------------------------------------------------- 58 | 59 | Copyright (c) 2018 **LLC "ION DV".** 60 | All rights reserved. -------------------------------------------------------------------------------- /docs/ru/4_ion_model/ion_environment.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/4_ion_model/ion_environment.md -------------------------------------------------------------------------------- /docs/ru/7_develop/app-utils/readme.md: -------------------------------------------------------------------------------- 1 | # Разработка функциональных утилит в приложении 2 | Функциональные утилиты приложения предназначены для решения специфичных задач приложения, без реализации отдельной логики в виде модуля. 3 | 4 | Например - утилиты вызываемой задачей по расписанию или утилиты вызываемой при переходе в бизнес-процессе. 5 | 6 | ## Содержание 7 | * утилиты для [задач по расписанию](./job.md) 8 | * утилиты для [бизнес-процесса](./workflow.md) 9 | * утилиты для [кнопки действия](./button.md) 10 | * утилиты для [веб-сервиса (модуль REST)](./rest.md) 11 | * утилиты для [печатных форм](./print-form.md) 12 | -------------------------------------------------------------------------------- /docs/ru/images/ION_logo_black_mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/ION_logo_black_mini.png -------------------------------------------------------------------------------- /docs/ru/images/Insta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/Insta.png -------------------------------------------------------------------------------- /docs/ru/images/app_structure1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/app_structure1.png -------------------------------------------------------------------------------- /docs/ru/images/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/facebook.png -------------------------------------------------------------------------------- /docs/ru/images/iondv_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/iondv_logo.png -------------------------------------------------------------------------------- /docs/ru/images/iondv_readme1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/iondv_readme1.png -------------------------------------------------------------------------------- /docs/ru/images/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/linkedin.png -------------------------------------------------------------------------------- /docs/ru/images/schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/schema.png -------------------------------------------------------------------------------- /docs/ru/images/sel_provider.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/sel_provider.jpg -------------------------------------------------------------------------------- /docs/ru/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/docs/ru/images/twitter.png -------------------------------------------------------------------------------- /i18n/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/i18n/.keep -------------------------------------------------------------------------------- /lib/deploy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Created by kras on 22.08.16. 4 | */ 5 | const appDeployer = require('./appSetup'); 6 | const read = require('core/readAppDeployConfig'); 7 | const {t} = require('core/i18n'); 8 | const {format} = require('util'); 9 | 10 | /** 11 | * @param {String} appDir 12 | * @param {{}} options 13 | * @param {Boolean} [options.overrideArrays] 14 | * @param {Boolean} [options.resetSettings] 15 | * @param {Boolean} [options.preserveModifiedSettings] 16 | * @param {SettingsRepository} options.settings 17 | * @returns {Promise.<*>} 18 | */ 19 | module.exports = function (appDir, options) { 20 | console.log(format(t('Application %s deployment'), appDir)); 21 | return read(appDir) 22 | .then((dep) => { 23 | let worker; 24 | if (dep) { 25 | if (dep.deployer) { 26 | if (dep.deployer === 'built-in') { 27 | worker = () => appDeployer(dep, options); 28 | } else { 29 | worker = require(dep.deployer); 30 | } 31 | if (typeof worker === 'function') { 32 | console.log(t('Application deployment script started')); 33 | return worker().then(() => dep); 34 | } 35 | } 36 | } 37 | }) 38 | .catch(err => { 39 | console.warn(err); 40 | console.warn(t('Failed to read deployment configuration.')); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /lib/duration.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @param {String | Number} time 4 | * @param {Boolean} [toMs] 5 | * @return {{value: String, unit: String} | null} 6 | */ 7 | function parseDuration(time, toMs) { 8 | if (time && typeof time === 'string') { 9 | let match = time.match(/(\d+)([smhdy])/); 10 | if (match && match[1]) { 11 | if (toMs) { 12 | let result = parseInt(match[1]); 13 | switch (match[2]) { 14 | case 's': 15 | return result * 1000; 16 | case 'm': 17 | return result * 60000; 18 | case 'h': 19 | return result * 3600000; 20 | case 'd': 21 | return result * 86400000; 22 | case 'y': 23 | return result * 365 * 86400000; 24 | default: 25 | return parseInt(result); 26 | } 27 | } 28 | return { 29 | value: parseInt(match[1]), 30 | unit: match[2] ? match[2] : 'm' 31 | }; 32 | } 33 | } 34 | if (time && typeof time === 'number') { 35 | return toMs ? time : {value: time, unit: 'm'}; 36 | } 37 | return null; 38 | } 39 | 40 | module.exports = parseDuration; -------------------------------------------------------------------------------- /lib/interfaces/ProfilePlugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 4/6/17. 3 | */ 4 | 'use strict'; 5 | 6 | function ProfilePlugin() { 7 | 8 | /** 9 | * 10 | * @return {Promise} 11 | */ 12 | this.fields = function () { 13 | return this._fields(); 14 | }; 15 | 16 | /** 17 | * @param {String} uid 18 | * @returns {Promise} 19 | */ 20 | this.properties = function (uid) { 21 | return this._properties(uid); 22 | }; 23 | 24 | /** 25 | * 26 | * @param {{}} data 27 | * @return {Promise} 28 | */ 29 | this.validate = function (data) { 30 | return this._validate(data); 31 | }; 32 | } 33 | 34 | module.exports = ProfilePlugin; 35 | -------------------------------------------------------------------------------- /lib/interfaces/StrategyProvider.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 05.04.19. 3 | */ 4 | 5 | function StrategyProvider() { 6 | this.getStrategy = function (conf, verify) { 7 | return this._getStrategy(conf, verify); 8 | }; 9 | } 10 | 11 | module.exports = StrategyProvider; -------------------------------------------------------------------------------- /lib/last-visit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kalias_90 on 13.11.17. 3 | */ 4 | 'use strict'; 5 | const cookie = require('cookie'); 6 | 7 | var disabled; 8 | 9 | module.exports = { 10 | enable: function () { 11 | disabled = false; 12 | }, 13 | disable: function () { 14 | disabled = true; 15 | }, 16 | get: function (req) { 17 | if (disabled) { 18 | return null; 19 | } 20 | let cks = req.cookies || cookie.parse(req.headers.cookie || ''); 21 | return cks.lastVisit; 22 | }, 23 | saver: function (req, res, next) { 24 | if (!disabled) { 25 | res.cookie('lastVisit', req.originalUrl); 26 | } 27 | next(); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /lib/util/crossNav.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 13.07.17. 3 | */ 4 | 5 | /** 6 | * @param {Array} nodes 7 | * @param {MetaRepository} metaRepo 8 | */ 9 | function parseNodes(nodes) { 10 | let result = []; 11 | nodes.forEach((n)=>{ 12 | if (n.type === 0) { 13 | result.push({ 14 | caption: n.caption, 15 | hint: n.hint, 16 | subnodes: parseNodes(n.children) 17 | }); 18 | } else if (n.type === 3) { 19 | result.push({ 20 | id: 'node_' + n.code, 21 | caption: n.caption, 22 | hint: n.hint, 23 | url: n.url, 24 | external: n.external 25 | }); 26 | } 27 | }); 28 | return result; 29 | } 30 | 31 | 32 | /** 33 | * @param {String} module 34 | * @param {MetaRepository} metaRepo 35 | * @param {SettingsRepository} settings 36 | */ 37 | module.exports = function (module, metaRepo, settings) { 38 | let sections = settings.get(module + '.crossNav'); 39 | let result = []; 40 | if (Array.isArray(sections)) { 41 | sections.forEach((s)=>{ 42 | let section = metaRepo.getNavigationSection(s); 43 | if (section) { 44 | let nodes = metaRepo.getNodes(s); 45 | if (nodes.length) { 46 | let node = { 47 | id: 'sect_' + section.name, 48 | caption: section.caption, 49 | subnodes: parseNodes(nodes) 50 | }; 51 | result.push(node); 52 | } 53 | } 54 | }); 55 | } 56 | return result; 57 | }; 58 | -------------------------------------------------------------------------------- /lib/util/extViews.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 15.02.17. 3 | */ 4 | 'use strict'; 5 | 6 | const resolvePath = require('core/resolvePath'); 7 | 8 | module.exports = function (app, views) { 9 | if (Array.isArray(views)) { 10 | let result = []; 11 | views.forEach(function (cv) { 12 | result.push(resolvePath(cv)); 13 | }); 14 | 15 | let current = app.get('views'); 16 | if (typeof current === 'string') { 17 | result.push(current); 18 | } else if (Array.isArray(current)) { 19 | Array.prototype.push.apply(result, current); 20 | } 21 | 22 | app.set('views', result); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /lib/util/staticRouter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Vasiliy Ermilov (ermilov.work@yandex.ru) on 1/16/17. 3 | */ 4 | const express = require('express'); 5 | const resolvePath = require('core/resolvePath'); 6 | 7 | /** 8 | * 9 | * @param {{name: String, path: String}[]}statics 10 | * @param {{maxAge: Number}[]}options 11 | * @return {*} 12 | */ 13 | module.exports = function (statics, options) { 14 | var router = express.Router(); 15 | var result = null; 16 | if (statics) { 17 | for (var name in statics) { 18 | if (statics.hasOwnProperty(name)) { 19 | router.use( 20 | (name[0] === '/' ? '' : '/') + name, 21 | express.static(resolvePath(statics[name]), options) 22 | ); 23 | if (!result) { 24 | result = router; 25 | } 26 | } 27 | } 28 | } 29 | return result; 30 | }; 31 | -------------------------------------------------------------------------------- /lib/util/sysMenuCheck.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const url = require('url'); 3 | 4 | /** 5 | * @param {Auth} auth 6 | * @param {Request} req 7 | * @param {Array} sysMenu 8 | */ 9 | function check(auth, req, sysMenu) { 10 | let result = []; 11 | let p = Promise.resolve(); 12 | if (Array.isArray(sysMenu)) { 13 | sysMenu.forEach((mi) => { 14 | p = p.then(() => { 15 | if (typeof mi !== 'object') { 16 | return true; 17 | } 18 | let path = '/' + mi.name; 19 | if (mi.url) { 20 | let u = url.parse(mi.url); 21 | if (u.host) { 22 | return true; 23 | } else { 24 | path = mi.url; 25 | } 26 | } 27 | return auth.checkPathAccess(req, path); 28 | }).then((can) => { 29 | if (can) { 30 | result.push(mi); 31 | } 32 | }); 33 | }); 34 | } 35 | return p.then(() => result); 36 | } 37 | 38 | module.exports = function (scope, app, module) { 39 | return function (req, res, next) { 40 | check(scope.auth, req, app.locals.sysMenu) 41 | .then((menu) => { 42 | res.locals.sysMenu = menu; 43 | let etmo = scope.settings.get(module + '.explicitTopMenu') || scope.settings.get('explicitTopMenu'); 44 | if (Array.isArray(etmo)) { 45 | return check(scope.auth, req, etmo); 46 | } 47 | return null; 48 | }) 49 | .then((expMenu) => { 50 | app.locals.explicitTopMenu = expMenu; 51 | next(); 52 | }) 53 | .catch((err) => { 54 | scope.sysLog.error(err); 55 | res.locals.sysMenu = []; 56 | next(); 57 | }); 58 | }; 59 | }; 60 | -------------------------------------------------------------------------------- /lib/util/viewResolver.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | 6 | module.exports = function (app) { 7 | return function (view, relativeTo = null, strict = false) { 8 | let paths = app.get('views'); 9 | if (!Array.isArray(paths)) { 10 | paths = [paths]; 11 | } 12 | for (let i = 0; i < paths.length; i++) { 13 | let fn = path.join(paths[i], view + '.ejs'); 14 | if (fs.existsSync(fn)) { 15 | if (relativeTo) { 16 | if (!fs.statSync(relativeTo).isDirectory()) { 17 | relativeTo = path.dirname(relativeTo); 18 | } 19 | let p = path.relative(relativeTo, fn); 20 | if (strict) { 21 | if (fs.existsSync(p)) { 22 | return p; 23 | } 24 | } else { 25 | return p; 26 | } 27 | } 28 | return fn; 29 | } 30 | } 31 | return strict ? false : view; 32 | }; 33 | }; 34 | -------------------------------------------------------------------------------- /modules/readme.md: -------------------------------------------------------------------------------- 1 | # Folder assignment 2 | The folder is intended for placing IONDV modules. 3 | 4 | ## Use in the product 5 | In each module(folder) in the product, the command must be executed `npm install --production` 6 | -------------------------------------------------------------------------------- /strings/errors/auth.js: -------------------------------------------------------------------------------- 1 | const codes = require('core/errors/auth'); 2 | const {w: t} = require('core/i18n'); 3 | 4 | module.exports = { 5 | [codes.NO_DS]: t(`Authentication datasource is not set up.`), 6 | [codes.FORBID]: t(`You dont have enough permissions to login.`), 7 | [codes.TMP_BLOCK]: t(`Account is blocked till %d`), 8 | [codes.FAIL]: t(`Failed to sign in.`), 9 | [codes.LACK_PWD]: t(`Account is not secured with password.`), 10 | [codes.UNAVAILABLE]: t(`Sign in is temporary unavailable due to technical reasons.`), 11 | [codes.NO_PWD]: t(`User password not specified`), 12 | [codes.INTERNAL_ERR]: t(`Internal server error`), 13 | [codes.BAD_PWD_REPEAT]: t(`Wrong password repeat!`), 14 | [codes.MIN_PWD_LENGTH]: t(`Minimal password length is %p symbols`), 15 | [codes.PRIOR_PWD]: t(`Using one of %p previous passwords is prohibited.`), 16 | [codes.WEAK_PWD]: t(`Password too weak. Password should contain `), 17 | [codes.UPPER_LOWER]: t(`letters in lower and upper case`), 18 | [codes.NUMBERS]: t(`numbers`), 19 | [codes.SPECIAL]: t(`special symbols (@, $, & etc.)`), 20 | [codes.AND]: t(`and`), 21 | [codes.REG_BAN]: t(`Public sign up is prohibited!`), 22 | [codes.REG_FAIL]: t(`User sign up failed!`), 23 | [codes.EDIT_USER_FAIL]: t(`Failed to edit user profile!`), 24 | [codes.PWD_BAN_NOT_FINISHED]: t(`Password change prohibition period was not ended.`), 25 | [codes.NOT_AUTHENTICATED]: t(`User was not authenicated.`), 26 | [codes.USER_BAN]: t(`User is blocked.`), 27 | [codes.BAD_USER_ID]: t(`Failed to determine user id.`), 28 | [codes.EXT_AUTH_FAIL]: t(`Failed to sign up user from external system.`), 29 | [codes.NO_STRATEGY]: t(`No strategy specified for passport %nm`) 30 | }; 31 | -------------------------------------------------------------------------------- /strings/errors/conditions.js: -------------------------------------------------------------------------------- 1 | const codes = require('core/errors/conditions'); 2 | const {w: t} = require('core/i18n'); 3 | 4 | module.exports = { 5 | [codes.NON_APPLICABLE]: t('Condition %condition is not applicable to attribute %class.%attr.'), 6 | [codes.ATTR_NOT_FOUND]: t('Attribute %class.%attr specified for condition is not found.'), 7 | [codes.INVALID_AGGREG]: t('Aggregation operation specification is invalid - class and attribute are not specified.'), 8 | [codes.INVALID_OPERATION]: t('Invalid operation type'), 9 | [codes.INVALID_CONDITION]: t('Invalid condition type'), 10 | [codes.NO_ARGS]: t('Operation arguments are not specified'), 11 | }; -------------------------------------------------------------------------------- /strings/errors/data-repo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | const codes = require('core/errors/data-repo'); 5 | const {w: t} = require('core/i18n'); 6 | 7 | module.exports = { 8 | [codes.ITEM_EXISTS]: t(`%class with this '%attr' value already exists.`), 9 | [codes.ITEM_EXISTS_MULTI]: t(`%class having same values of '%attr' already exists.`), 10 | [codes.ITEM_NOT_FOUND]: t(`Object '%info' not found.`), 11 | [codes.EXISTS_IN_COL]: t(`Object '%info' is aleady in collection '%col'.`), 12 | [codes.BAD_PARAMS]: t(`Invalid parameters specified for method '%method'.`), 13 | [codes.FILE_ATTR_SAVE]: t(`Failed to save data to file attribute '%attr' of object '%info'.`), 14 | [codes.FILE_ATTR_LOAD]: t(`Failed to load file attribute '%attr'.`), 15 | [codes.NO_COLLECTION]: t(`collection '%attr' is abscent in object %info.`), 16 | [codes.INVALID_META]: t(`Error in meta-model of object '%info'.`), 17 | [codes.COMPOSITE_KEY]: t(`Using complex keys in operation '%oper' is not supported yet.`), 18 | [codes.FAIL]: t(`'%operation' action was not applied to object '%info'.`), 19 | [codes.MISSING_REQUIRED]: t(`Required attributes are not set for object %info.`), 20 | [codes.NO_KEY_SPEC]: t(`Key attribute value not set for object %info.`), 21 | [codes.NO_BACK_REF]: t(`Attribute %backAttr not found for back reference %backRef.`), 22 | [codes.UNEXPECTED_ASYNC]: t(`Async operation performed when calculation the default value for attribute %info.`), 23 | [codes.PERMISSION_LACK]: t(`Not enough permissions for action`) 24 | }; 25 | -------------------------------------------------------------------------------- /strings/errors/data-source.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const codes = require('core/errors/data-source'); 6 | const {w: t} = require('core/i18n'); 7 | 8 | module.exports = { 9 | [codes.UNIQUENESS_VIOLATION]: t(`Uniqueness of key '%key' of dataset '%table' is violated`), 10 | [codes.BAD_QUERY]: t(`Error in query.`), 11 | [codes.OPER_FAILED]: t(`Operation '%oper' was not applied to '%table' dataset.`) 12 | }; 13 | -------------------------------------------------------------------------------- /strings/errors/di.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | module.exports = {}; 5 | -------------------------------------------------------------------------------- /strings/errors/file-storage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const codes = require('core/errors/file-storage'); 6 | const {w: t} = require('core/i18n'); 7 | 8 | module.exports = { 9 | [codes.BAD_DATA]: t(`Invalid data format.`), 10 | [codes.NO_DIR]: t(`Directory '%dir' not found.`), 11 | [codes.NO_FILE]: t(`File '%file' not found.`) 12 | }; 13 | -------------------------------------------------------------------------------- /strings/errors/front-end.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 08.05.17. 3 | */ 4 | const codes = require('core/errors/front-end'); 5 | const {w: t} = require('core/i18n'); 6 | 7 | module.exports = { 8 | [codes.ACCESS_DENIED]: t(`Access level not enough for the action.`) 9 | }; 10 | -------------------------------------------------------------------------------- /strings/errors/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | const merge = require('merge'); 5 | 6 | module.exports = merge( 7 | require('./auth'), 8 | require('./data-repo'), 9 | require('./data-source'), 10 | require('./di'), 11 | require('./file-storage'), 12 | require('./meta-repo'), 13 | require('./workflow'), 14 | require('./validation'), 15 | require('./front-end') 16 | ); 17 | 18 | -------------------------------------------------------------------------------- /strings/errors/meta-repo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const codes = require('core/errors/meta-repo'); 6 | const {w: t} = require('core/i18n'); 7 | 8 | module.exports = { 9 | [codes.NO_CLASS]: t('Class %class not found in namespace %namespace.'), 10 | [codes.NO_ATTR]: t('Attribute \'%attr\' not found in class \'%class\'.'), 11 | [codes.NO_VIEW]: t('View \'%view\' not found.'), 12 | [codes.NO_WORKFLOW]: t('Workflow \'%workflow\' not found.') 13 | }; 14 | -------------------------------------------------------------------------------- /strings/errors/validation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by kalias_90 on 23.05.17. 3 | */ 4 | 'use strict'; 5 | 6 | const codes = require('core/errors/validation'); 7 | const {w: t} = require('core/i18n'); 8 | 9 | const defaultMessage = t('Invalid value assigned to attribute %class.%property.'); 10 | const messageForRealAndDecimal = t('Attribute %class.%property value should be a number (fractional part should be separated with dot).'); 11 | const messageForDatetimeAndPeriod = t('Invalid date value assigned to attribute %class.%property.'); 12 | 13 | module.exports = { 14 | [codes.INCORRECT_VALUE.INT]: t('Attribute %class.%property value should be an integer number.'), 15 | [codes.INCORRECT_VALUE.REAL]: messageForRealAndDecimal, 16 | [codes.INCORRECT_VALUE.DECIMAL]: messageForRealAndDecimal, 17 | [codes.INCORRECT_VALUE.DATETIME]: messageForDatetimeAndPeriod, 18 | [codes.INCORRECT_VALUE.PERIOD]: messageForDatetimeAndPeriod, 19 | [codes.INCORRECT_VALUE.DEFAULT]: defaultMessage 20 | }; 21 | -------------------------------------------------------------------------------- /strings/errors/workflow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by krasilneg on 25.04.17. 3 | */ 4 | 'use strict'; 5 | const codes = require('core/errors/workflow'); 6 | const {w: t} = require('core/i18n'); 7 | 8 | module.exports = { 9 | [codes.ACCESS_DENIED]: t(`Access level not enough to perform workflow transition '%trans'`), 10 | [codes.WORKFLOW_NOT_FOUND]: t(`Workflow '%workflow' not found.`), 11 | [codes.TRANS_ERROR]: t(`Transition '%trans' failed.`), 12 | [codes.STATE_NOT_FOUND]: t(`Status '%state' of workflow '%workflow' not found.`), 13 | [codes.CONDITION_VIOLATION]: 14 | t(`Object '%info' does not satisfy conditions of final state '%state' of workflow '%workflow'.`), 15 | [codes.NOT_IN_WORKFLOW]: t(`Object '%info' is not in workflow '%workflow'.`), 16 | [codes.TRANS_IMPOSSIBLE]: t(`Transition '%trans' of workflow '%workflow' is not allowed.`), 17 | [codes.TRANS_NOT_FOUND]: t(`Transition '%trans' of workflow '%workflow' not found.`), 18 | [codes.IN_WORKFLOW]: t(`Object is already in workflow '%workflow'`) 19 | }; 20 | -------------------------------------------------------------------------------- /strings/frontend.js: -------------------------------------------------------------------------------- 1 | const {w: t} = require('core/i18n'); 2 | 3 | module.exports = { 4 | "js.profile.required": t("Field %field value is required") 5 | }; 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /strings/templates-default.js: -------------------------------------------------------------------------------- 1 | const {w: t} = require('core/i18n'); 2 | 3 | module.exports = { 4 | "templates.default.home": t("Home"), 5 | "templates.default.login": t("Login"), 6 | "templates.default.password": t("Password"), 7 | "templates.default.repeatPwd": t("Repeat password"), 8 | "templates.default.enter": t("Sign in"), 9 | "templates.default.login.title": t("Sign in form"), 10 | "templates.default.login.register": t("Sign up"), 11 | "templates.default.login.signin": t("Enter"), 12 | "templates.default.changePwd.title": t("Password change form"), 13 | "templates.default.changePwd.newPwd": t("New password"), 14 | "templates.default.changePwd.changePwd": t("Change password"), 15 | "templates.default.oauthGrant.title": t("OAuth2 access request"), 16 | "templates.default.oauthGrant.claim": t("Application %app claims access with your account"), 17 | "templates.default.oauthGrant.grant": t("Grant access"), 18 | "templates.default.oauthGrant.deny": t("Deny access"), 19 | "templates.default.profile.title": t("User %name profile"), 20 | "templates.default.profile.save": t("Save"), 21 | "templates.default.profile.back": t("Back to application"), 22 | "templates.default.profile.language": t("Language"), 23 | "templates.default.register.title": t("Sign up form"), 24 | "templates.default.register.register": t("Sign up") 25 | } 26 | -------------------------------------------------------------------------------- /test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | mocha: true # adds all of the Mocha testing global variables 3 | protractor: true # Protractor global variables 4 | globals: 5 | app: false 6 | assert: true 7 | ionTestParam: true 8 | page: true 9 | browser: true 10 | describe: true 11 | it: true 12 | before: true 13 | after: true 14 | rules: 15 | no-console: off 16 | no-sync: off # It is allowed to use synchronous functions in the test 17 | no-invalid-this: off # We allow the use of this - necessary for mocha 18 | -------------------------------------------------------------------------------- /test/quality/files-format.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Testing the compliance of meta files with the format JSON 3 | */ 4 | const path = require('path'); 5 | 6 | const processDir = require('core/util/read').processDir; 7 | 8 | describe('# Checking whether metadata files match the formats', function () { 9 | this.timeout(120000); 10 | const pathApp = path.join(__dirname, '../../applications'); 11 | it('Checking for format compliance JSON in ' + pathApp, (done) => { 12 | let filesList = []; 13 | let errFiles = []; 14 | processDir(pathApp, 15 | (nm) => {return nm.substr(-5) === '.json';}, 16 | (fn) => {if (fn.indexOf('node_modules') === -1) { 17 | filesList.push(fn); 18 | try { 19 | require(fn); 20 | } catch (err) { 21 | errFiles.push(fn); 22 | console.error('Error in', err.message); 23 | } 24 | }}, 25 | (err) => {console.error('File reading error', err);}); 26 | if (errFiles.length) { 27 | done(new Error ('There is an error in the format in the metadata and data files JSON')); 28 | } else { 29 | console.info('Verified JSON files', filesList.length); 30 | done(); 31 | } 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/readme.md: -------------------------------------------------------------------------------- 1 | # Folder assignment 2 | The folder is intended for placing tests 3 | 4 | ## Use in the product 5 | Folder when you build the distribution package is not added to the project 6 | -------------------------------------------------------------------------------- /view/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true # browser global variables TODO - в папку скриптов остальных модулей 3 | jquery: true # jQuery global variables TODO - в папку скриптов остальных модулей 4 | # es6: false # enable all ECMAScript 6 features except for modules 5 | parserOptions: 6 | #ecmaVersion: 6 # specify the version of ECMAScript 7 | sourceType: script # Тип настроек линта - для скриптов 8 | rules: 9 | no-alert: error # Запрет на allert и другие методы - которые нельзя в браузере протыкать - Откл.в recommended 10 | no-implicit-globals: warn # Не разрешается объявление функций и переменных глобально - Откл.в recommended 11 | no-iterator: error # Запрет испльзования __iterator__ в скриптах - Откл.в recommended 12 | no-script-url: error # Запрет для javascript:url - анало eval - Откл.в recommended 13 | strict: off # Не обязательный strict режим для скриптов 14 | no-var: off # Разрешаем использования var 15 | 16 | -------------------------------------------------------------------------------- /view/default/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/favicon.ico -------------------------------------------------------------------------------- /view/default/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /view/default/static/fonts/et-line.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/et-line.eot -------------------------------------------------------------------------------- /view/default/static/fonts/et-line.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/et-line.ttf -------------------------------------------------------------------------------- /view/default/static/fonts/et-line.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/et-line.woff -------------------------------------------------------------------------------- /view/default/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /view/default/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /view/default/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /view/default/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /view/default/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /view/default/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /view/default/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /view/default/static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /view/default/static/img/ico-lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/img/ico-lock.png -------------------------------------------------------------------------------- /view/default/static/img/ico-user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iondv/framework/5c08e6659bb101cc64f751339e28f9036c773522/view/default/static/img/ico-user.png -------------------------------------------------------------------------------- /view/default/static/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iondv-framework-view-default-theme", 3 | "version": "1.0.0", 4 | "description": "Frontend packages for module iondv. framework theme", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/iondv/framework.git" 8 | }, 9 | "license": "Apache-2.0", 10 | "vendorDir": "./vendor", 11 | "dependencies": { 12 | "bootstrap": "^3.4.1", 13 | "font-awesome": "^4.7.0", 14 | "jquery": "^3.4", 15 | "gettext.js": "*", 16 | "moment": "^2.24.0", 17 | "moment-timezone": "^0.5.23" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /view/default/templates/403.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ION: <%=t('Access denied')%> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /view/default/templates/oauth-grant.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= pageTitle %>: <%=__('templates.default.oauthGrant.title')%> 5 | 6 | 7 | 8 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 40 |
41 | <%- typeof pageEndContent !== 'undefined' ? pageEndContent : "" %> 42 | 43 | 44 | --------------------------------------------------------------------------------