├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .firebaserc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── docker-build.yml │ └── unit-test.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── LICENSE ├── README.md ├── angular.json ├── api-docs └── api.github.com.2022-11-28.yaml ├── cloudbuild.yaml ├── cors.json ├── firebase.json ├── firestore.indexes.json ├── firestore.rules ├── functions ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── package-lock.json ├── package.json ├── src │ ├── assets.ts │ ├── config.ts │ ├── contents.ts │ ├── index.ts │ ├── models │ │ ├── asset.model.ts │ │ ├── asset.zod.ts │ │ ├── content-history.model.ts │ │ ├── content.model.ts │ │ ├── content.zod.ts │ │ ├── firebase.model.ts │ │ ├── index.ts │ │ ├── locale.model.ts │ │ ├── open-api.model.ts │ │ ├── schema.model.ts │ │ ├── schema.zod.ts │ │ ├── space.model.ts │ │ ├── task.model.ts │ │ ├── token.model.ts │ │ ├── translate.model.ts │ │ ├── translation-history.model.ts │ │ ├── translation.model.ts │ │ ├── translation.zod.ts │ │ └── user.model.ts │ ├── open-api.ts │ ├── plugins │ │ └── unsplash │ │ │ ├── api.ts │ │ │ └── models.ts │ ├── services │ │ ├── asset.service.ts │ │ ├── content-history.service.ts │ │ ├── content.service.ts │ │ ├── index.ts │ │ ├── open-api.service.ts │ │ ├── schema.service.ts │ │ ├── space.service.ts │ │ ├── task.service.ts │ │ ├── token.service.ts │ │ ├── translate.service.ts │ │ ├── translation-history.service.ts │ │ ├── translation.service.ts │ │ └── user.service.ts │ ├── setup.ts │ ├── spaces.ts │ ├── storage.ts │ ├── tasks.ts │ ├── translate.ts │ ├── translations.ts │ ├── users.ts │ ├── utils │ │ └── security-utils.ts │ └── v1.ts ├── tsconfig.dev.json └── tsconfig.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── proxy.conf.js ├── remoteconfig.template.json ├── scripts ├── sync-v1.css └── sync-v1.ts ├── src ├── _app-theme.scss ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── app │ ├── app-routing.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.ts │ ├── app.config.ts │ ├── core │ │ ├── core.module.ts │ │ ├── error-handler │ │ │ ├── app-error-handler.service.ts │ │ │ └── form-error-handler.service.ts │ │ ├── http-interceptors │ │ │ └── http-error.interceptor.ts │ │ ├── title │ │ │ └── page-title.strategy.ts │ │ └── utils │ │ │ ├── name-utils.service.spec.ts │ │ │ ├── name-utils.service.ts │ │ │ ├── object-utils.service.spec.ts │ │ │ └── object-utils.service.ts │ ├── features │ │ ├── _features-theme.scss │ │ ├── admin │ │ │ ├── settings │ │ │ │ ├── settings-routing.module.ts │ │ │ │ ├── settings.component.html │ │ │ │ ├── settings.component.scss │ │ │ │ ├── settings.component.ts │ │ │ │ ├── settings.module.ts │ │ │ │ └── ui │ │ │ │ │ ├── ui.component.html │ │ │ │ │ ├── ui.component.scss │ │ │ │ │ └── ui.component.ts │ │ │ ├── spaces │ │ │ │ ├── space-dialog │ │ │ │ │ ├── space-dialog.component.html │ │ │ │ │ ├── space-dialog.component.scss │ │ │ │ │ ├── space-dialog.component.ts │ │ │ │ │ └── space-dialog.model.ts │ │ │ │ ├── spaces-routing.module.ts │ │ │ │ ├── spaces.component.html │ │ │ │ ├── spaces.component.scss │ │ │ │ ├── spaces.component.ts │ │ │ │ └── spaces.module.ts │ │ │ └── users │ │ │ │ ├── user-dialog │ │ │ │ ├── user-dialog.component.html │ │ │ │ ├── user-dialog.component.scss │ │ │ │ ├── user-dialog.component.ts │ │ │ │ └── user-dialog.model.ts │ │ │ │ ├── user-invite-dialog │ │ │ │ ├── user-invite-dialog.component.html │ │ │ │ ├── user-invite-dialog.component.scss │ │ │ │ ├── user-invite-dialog.component.ts │ │ │ │ └── user-invite-dialog.model.ts │ │ │ │ ├── users-routing.module.ts │ │ │ │ ├── users.component.html │ │ │ │ ├── users.component.scss │ │ │ │ ├── users.component.ts │ │ │ │ └── users.module.ts │ │ ├── features-routing.module.ts │ │ ├── features.component.html │ │ ├── features.component.scss │ │ ├── features.component.ts │ │ ├── features.module.ts │ │ ├── me │ │ │ ├── me-dialog │ │ │ │ ├── me-dialog.component.html │ │ │ │ ├── me-dialog.component.scss │ │ │ │ ├── me-dialog.component.ts │ │ │ │ └── me-dialog.model.ts │ │ │ ├── me-email-dialog │ │ │ │ ├── me-email-dialog.component.html │ │ │ │ ├── me-email-dialog.component.scss │ │ │ │ ├── me-email-dialog.component.ts │ │ │ │ └── me-email-dialog.model.ts │ │ │ ├── me-password-dialog │ │ │ │ ├── me-password-dialog.component.html │ │ │ │ ├── me-password-dialog.component.scss │ │ │ │ ├── me-password-dialog.component.ts │ │ │ │ └── me-password-dialog.model.ts │ │ │ ├── me-routing.module.ts │ │ │ ├── me.component.html │ │ │ ├── me.component.scss │ │ │ ├── me.component.ts │ │ │ └── me.module.ts │ │ ├── spaces │ │ │ ├── assets │ │ │ │ ├── add-folder-dialog │ │ │ │ │ ├── add-folder-dialog.component.html │ │ │ │ │ ├── add-folder-dialog.component.scss │ │ │ │ │ ├── add-folder-dialog.component.ts │ │ │ │ │ └── add-folder-dialog.model.ts │ │ │ │ ├── assets-routing.module.ts │ │ │ │ ├── assets.component.html │ │ │ │ ├── assets.component.scss │ │ │ │ ├── assets.component.ts │ │ │ │ ├── assets.module.ts │ │ │ │ ├── edit-file-dialog │ │ │ │ │ ├── edit-file-dialog.component.html │ │ │ │ │ ├── edit-file-dialog.component.scss │ │ │ │ │ ├── edit-file-dialog.component.ts │ │ │ │ │ └── edit-file-dialog.model.ts │ │ │ │ ├── edit-folder-dialog │ │ │ │ │ ├── edit-folder-dialog.component.html │ │ │ │ │ ├── edit-folder-dialog.component.scss │ │ │ │ │ ├── edit-folder-dialog.component.ts │ │ │ │ │ └── edit-folder-dialog.model.ts │ │ │ │ ├── export-dialog │ │ │ │ │ ├── export-dialog.component.html │ │ │ │ │ ├── export-dialog.component.scss │ │ │ │ │ ├── export-dialog.component.ts │ │ │ │ │ └── export-dialog.model.ts │ │ │ │ ├── import-dialog │ │ │ │ │ ├── import-dialog.component.html │ │ │ │ │ ├── import-dialog.component.scss │ │ │ │ │ ├── import-dialog.component.ts │ │ │ │ │ └── import-dialog.model.ts │ │ │ │ └── move-dialog │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── move-dialog.component.html │ │ │ │ │ ├── move-dialog.component.scss │ │ │ │ │ ├── move-dialog.component.ts │ │ │ │ │ └── move-dialog.model.ts │ │ │ ├── contents │ │ │ │ ├── add-document-dialog │ │ │ │ │ ├── add-document-dialog.component.html │ │ │ │ │ ├── add-document-dialog.component.scss │ │ │ │ │ ├── add-document-dialog.component.ts │ │ │ │ │ ├── add-document-dialog.model.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── add-folder-dialog │ │ │ │ │ ├── add-folder-dialog.component.html │ │ │ │ │ ├── add-folder-dialog.component.scss │ │ │ │ │ ├── add-folder-dialog.component.ts │ │ │ │ │ ├── add-folder-dialog.model.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── contents-routing.module.ts │ │ │ │ ├── contents.component.html │ │ │ │ ├── contents.component.scss │ │ │ │ ├── contents.component.ts │ │ │ │ ├── contents.module.ts │ │ │ │ ├── edit-dialog │ │ │ │ │ ├── edit-dialog.component.html │ │ │ │ │ ├── edit-dialog.component.scss │ │ │ │ │ ├── edit-dialog.component.ts │ │ │ │ │ ├── edit-dialog.model.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── edit-document-schema │ │ │ │ │ ├── edit-document-schema.component.html │ │ │ │ │ ├── edit-document-schema.component.scss │ │ │ │ │ ├── edit-document-schema.component.ts │ │ │ │ │ └── edit-document-schema.model.ts │ │ │ │ ├── edit-document │ │ │ │ │ ├── edit-document.component.html │ │ │ │ │ ├── edit-document.component.scss │ │ │ │ │ ├── edit-document.component.ts │ │ │ │ │ └── edit-document.model.ts │ │ │ │ ├── export-dialog │ │ │ │ │ ├── export-dialog.component.html │ │ │ │ │ ├── export-dialog.component.scss │ │ │ │ │ ├── export-dialog.component.ts │ │ │ │ │ ├── export-dialog.model.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── import-dialog │ │ │ │ │ ├── import-dialog.component.html │ │ │ │ │ ├── import-dialog.component.scss │ │ │ │ │ ├── import-dialog.component.ts │ │ │ │ │ ├── import-dialog.model.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── move-dialog │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── move-dialog.component.html │ │ │ │ │ ├── move-dialog.component.scss │ │ │ │ │ ├── move-dialog.component.ts │ │ │ │ │ └── move-dialog.model.ts │ │ │ │ └── shared │ │ │ │ │ ├── asset-select │ │ │ │ │ ├── asset-select.component.html │ │ │ │ │ ├── asset-select.component.scss │ │ │ │ │ └── asset-select.component.ts │ │ │ │ │ ├── assets-select │ │ │ │ │ ├── assets-select.component.html │ │ │ │ │ ├── assets-select.component.scss │ │ │ │ │ └── assets-select.component.ts │ │ │ │ │ ├── link-select │ │ │ │ │ ├── link-select.component.html │ │ │ │ │ ├── link-select.component.scss │ │ │ │ │ └── link-select.component.ts │ │ │ │ │ ├── reference-select │ │ │ │ │ ├── reference-select.component.html │ │ │ │ │ ├── reference-select.component.scss │ │ │ │ │ └── reference-select.component.ts │ │ │ │ │ ├── references-select │ │ │ │ │ ├── references-select.component.html │ │ │ │ │ ├── references-select.component.scss │ │ │ │ │ └── references-select.component.ts │ │ │ │ │ └── rich-text-editor │ │ │ │ │ ├── rich-text-editor.component.html │ │ │ │ │ ├── rich-text-editor.component.scss │ │ │ │ │ └── rich-text-editor.component.ts │ │ │ ├── dashboard │ │ │ │ ├── dashboard-routing.module.ts │ │ │ │ ├── dashboard.component.html │ │ │ │ ├── dashboard.component.scss │ │ │ │ ├── dashboard.component.ts │ │ │ │ └── dashboard.module.ts │ │ │ ├── open-api │ │ │ │ ├── open-api-routing.module.ts │ │ │ │ ├── open-api.component.html │ │ │ │ ├── open-api.component.scss │ │ │ │ ├── open-api.component.ts │ │ │ │ └── open-api.module.ts │ │ │ ├── schemas │ │ │ │ ├── add-dialog │ │ │ │ │ ├── add-dialog.component.html │ │ │ │ │ ├── add-dialog.component.scss │ │ │ │ │ ├── add-dialog.component.ts │ │ │ │ │ └── add-dialog.model.ts │ │ │ │ ├── edit-comp │ │ │ │ │ ├── edit-comp.component.html │ │ │ │ │ ├── edit-comp.component.scss │ │ │ │ │ └── edit-comp.component.ts │ │ │ │ ├── edit-enum │ │ │ │ │ ├── edit-enum.component.html │ │ │ │ │ ├── edit-enum.component.scss │ │ │ │ │ └── edit-enum.component.ts │ │ │ │ ├── edit-id-dialog │ │ │ │ │ ├── edit-id-dialog.component.html │ │ │ │ │ ├── edit-id-dialog.component.scss │ │ │ │ │ ├── edit-id-dialog.component.ts │ │ │ │ │ ├── edit-id-dialog.model.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── export-dialog │ │ │ │ │ ├── export-dialog.component.html │ │ │ │ │ ├── export-dialog.component.scss │ │ │ │ │ ├── export-dialog.component.ts │ │ │ │ │ └── export-dialog.model.ts │ │ │ │ ├── import-dialog │ │ │ │ │ ├── import-dialog.component.html │ │ │ │ │ ├── import-dialog.component.scss │ │ │ │ │ ├── import-dialog.component.ts │ │ │ │ │ └── import-dialog.model.ts │ │ │ │ ├── schemas-routing.module.ts │ │ │ │ ├── schemas.component.html │ │ │ │ ├── schemas.component.scss │ │ │ │ ├── schemas.component.ts │ │ │ │ ├── schemas.module.ts │ │ │ │ └── shared │ │ │ │ │ ├── edit-field │ │ │ │ │ ├── edit-field.component.html │ │ │ │ │ ├── edit-field.component.scss │ │ │ │ │ └── edit-field.component.ts │ │ │ │ │ └── edit-value │ │ │ │ │ ├── edit-value.component.html │ │ │ │ │ ├── edit-value.component.scss │ │ │ │ │ └── edit-value.component.ts │ │ │ ├── settings │ │ │ │ ├── general │ │ │ │ │ ├── general.component.html │ │ │ │ │ ├── general.component.scss │ │ │ │ │ └── general.component.ts │ │ │ │ ├── locales │ │ │ │ │ ├── locale-dialog │ │ │ │ │ │ ├── locale-dialog.component.html │ │ │ │ │ │ ├── locale-dialog.component.scss │ │ │ │ │ │ ├── locale-dialog.component.ts │ │ │ │ │ │ └── locale-dialog.model.ts │ │ │ │ │ ├── locales.component.html │ │ │ │ │ ├── locales.component.scss │ │ │ │ │ └── locales.component.ts │ │ │ │ ├── settings-routing.module.ts │ │ │ │ ├── settings.component.html │ │ │ │ ├── settings.component.scss │ │ │ │ ├── settings.component.ts │ │ │ │ ├── settings.module.ts │ │ │ │ ├── tokens │ │ │ │ │ ├── token-dialog │ │ │ │ │ │ ├── token-dialog.component.html │ │ │ │ │ │ ├── token-dialog.component.scss │ │ │ │ │ │ ├── token-dialog.component.ts │ │ │ │ │ │ └── token-dialog.model.ts │ │ │ │ │ ├── tokens.component.html │ │ │ │ │ ├── tokens.component.scss │ │ │ │ │ └── tokens.component.ts │ │ │ │ └── visual-editor │ │ │ │ │ ├── visual-editor.component.html │ │ │ │ │ ├── visual-editor.component.scss │ │ │ │ │ └── visual-editor.component.ts │ │ │ ├── tasks │ │ │ │ ├── tasks-routing.module.ts │ │ │ │ ├── tasks.component.html │ │ │ │ ├── tasks.component.scss │ │ │ │ ├── tasks.component.ts │ │ │ │ └── tasks.module.ts │ │ │ └── translations │ │ │ │ ├── add-dialog │ │ │ │ ├── add-dialog.component.html │ │ │ │ ├── add-dialog.component.scss │ │ │ │ ├── add-dialog.component.ts │ │ │ │ ├── add-dialog.model.ts │ │ │ │ └── index.ts │ │ │ │ ├── edit-dialog │ │ │ │ ├── edit-dialog.component.html │ │ │ │ ├── edit-dialog.component.scss │ │ │ │ ├── edit-dialog.component.ts │ │ │ │ ├── edit-dialog.model.ts │ │ │ │ └── index.ts │ │ │ │ ├── edit-id-dialog │ │ │ │ ├── edit-id-dialog.component.html │ │ │ │ ├── edit-id-dialog.component.scss │ │ │ │ ├── edit-id-dialog.component.ts │ │ │ │ ├── edit-id-dialog.model.ts │ │ │ │ └── index.ts │ │ │ │ ├── export-dialog │ │ │ │ ├── export-dialog.component.html │ │ │ │ ├── export-dialog.component.scss │ │ │ │ ├── export-dialog.component.ts │ │ │ │ └── export-dialog.model.ts │ │ │ │ ├── import-dialog │ │ │ │ ├── import-dialog.component.html │ │ │ │ ├── import-dialog.component.scss │ │ │ │ ├── import-dialog.component.ts │ │ │ │ └── import-dialog.model.ts │ │ │ │ ├── shared │ │ │ │ └── models │ │ │ │ │ └── translation.model.ts │ │ │ │ ├── translation-array-edit │ │ │ │ ├── translation-array-edit.component.html │ │ │ │ ├── translation-array-edit.component.scss │ │ │ │ └── translation-array-edit.component.ts │ │ │ │ ├── translation-array-view │ │ │ │ ├── translation-array-view.component.html │ │ │ │ ├── translation-array-view.component.scss │ │ │ │ └── translation-array-view.component.ts │ │ │ │ ├── translation-plural-edit │ │ │ │ ├── translation-plural-edit.component.html │ │ │ │ ├── translation-plural-edit.component.scss │ │ │ │ └── translation-plural-edit.component.ts │ │ │ │ ├── translation-plural-view │ │ │ │ ├── translation-plural-view.component.html │ │ │ │ ├── translation-plural-view.component.scss │ │ │ │ └── translation-plural-view.component.ts │ │ │ │ ├── translation-string-edit │ │ │ │ ├── translation-string-edit.component.html │ │ │ │ ├── translation-string-edit.component.scss │ │ │ │ └── translation-string-edit.component.ts │ │ │ │ ├── translation-string-view │ │ │ │ ├── translation-string-view.component.html │ │ │ │ ├── translation-string-view.component.scss │ │ │ │ └── translation-string-view.component.ts │ │ │ │ ├── translations-routing.module.ts │ │ │ │ ├── translations.component.html │ │ │ │ ├── translations.component.scss │ │ │ │ ├── translations.component.ts │ │ │ │ └── translations.module.ts │ │ └── welcome │ │ │ ├── welcome.component.html │ │ │ ├── welcome.component.scss │ │ │ └── welcome.component.ts │ ├── login │ │ ├── login.component.html │ │ ├── login.component.scss │ │ └── login.component.ts │ ├── reset │ │ ├── reset.component.html │ │ ├── reset.component.scss │ │ └── reset.component.ts │ ├── setup │ │ ├── setup.component.html │ │ ├── setup.component.scss │ │ ├── setup.component.ts │ │ ├── setup.model.ts │ │ └── setup.service.ts │ └── shared │ │ ├── components │ │ ├── assets-select-dialog │ │ │ ├── assets-select-dialog.component.html │ │ │ ├── assets-select-dialog.component.scss │ │ │ ├── assets-select-dialog.component.ts │ │ │ └── assets-select-dialog.model.ts │ │ ├── breadcrumb │ │ │ ├── breadcrumb-item.component.html │ │ │ ├── breadcrumb-item.component.scss │ │ │ ├── breadcrumb-item.component.ts │ │ │ ├── breadcrumb.component.html │ │ │ ├── breadcrumb.component.scss │ │ │ ├── breadcrumb.component.ts │ │ │ └── index.ts │ │ ├── confirmation-dialog │ │ │ ├── confirmation-dialog.component.html │ │ │ ├── confirmation-dialog.component.scss │ │ │ ├── confirmation-dialog.component.ts │ │ │ ├── confirmation-dialog.model.ts │ │ │ └── index.ts │ │ ├── custom-snack-bar │ │ │ ├── custom-snack-bar.component.html │ │ │ ├── custom-snack-bar.component.scss │ │ │ ├── custom-snack-bar.component.ts │ │ │ └── custom-snack-bar.model.ts │ │ ├── image-preview-dialog │ │ │ ├── image-preview-dialog.component.html │ │ │ ├── image-preview-dialog.component.scss │ │ │ ├── image-preview-dialog.component.ts │ │ │ └── image-preview-dialog.model.ts │ │ ├── references-select-dialog │ │ │ ├── index.ts │ │ │ ├── references-select-dialog.component.html │ │ │ ├── references-select-dialog.component.scss │ │ │ ├── references-select-dialog.component.ts │ │ │ └── references-select-dialog.model.ts │ │ ├── status │ │ │ ├── index.ts │ │ │ ├── status.component.html │ │ │ ├── status.component.scss │ │ │ ├── status.component.ts │ │ │ └── status.model.ts │ │ └── unsplash-assets-select-dialog │ │ │ ├── index.ts │ │ │ ├── unsplash-assets-select-dialog.component.html │ │ │ ├── unsplash-assets-select-dialog.component.scss │ │ │ ├── unsplash-assets-select-dialog.component.ts │ │ │ └── unsplash-assets-select-dialog.model.ts │ │ ├── directives │ │ ├── animate.directive.ts │ │ ├── file-drag-and-drop.directive.ts │ │ └── image-preview.directive.ts │ │ ├── generated │ │ └── github │ │ │ ├── api-configuration.ts │ │ │ ├── api.module.ts │ │ │ ├── base-service.ts │ │ │ ├── fn │ │ │ └── repos │ │ │ │ ├── repos-accept-invitation-for-authenticated-user.ts │ │ │ │ ├── repos-add-app-access-restrictions.ts │ │ │ │ ├── repos-add-collaborator.ts │ │ │ │ ├── repos-add-status-check-contexts.ts │ │ │ │ ├── repos-add-team-access-restrictions.ts │ │ │ │ ├── repos-add-user-access-restrictions.ts │ │ │ │ ├── repos-check-automated-security-fixes.ts │ │ │ │ ├── repos-check-collaborator.ts │ │ │ │ ├── repos-check-vulnerability-alerts.ts │ │ │ │ ├── repos-codeowners-errors.ts │ │ │ │ ├── repos-compare-commits.ts │ │ │ │ ├── repos-create-autolink.ts │ │ │ │ ├── repos-create-commit-comment.ts │ │ │ │ ├── repos-create-commit-signature-protection.ts │ │ │ │ ├── repos-create-commit-status.ts │ │ │ │ ├── repos-create-deploy-key.ts │ │ │ │ ├── repos-create-deployment-branch-policy.ts │ │ │ │ ├── repos-create-deployment-protection-rule.ts │ │ │ │ ├── repos-create-deployment-status.ts │ │ │ │ ├── repos-create-deployment.ts │ │ │ │ ├── repos-create-dispatch-event.ts │ │ │ │ ├── repos-create-for-authenticated-user.ts │ │ │ │ ├── repos-create-fork.ts │ │ │ │ ├── repos-create-in-org.ts │ │ │ │ ├── repos-create-or-update-environment.ts │ │ │ │ ├── repos-create-or-update-file-contents.ts │ │ │ │ ├── repos-create-org-ruleset.ts │ │ │ │ ├── repos-create-pages-deployment.ts │ │ │ │ ├── repos-create-pages-site.ts │ │ │ │ ├── repos-create-release.ts │ │ │ │ ├── repos-create-repo-ruleset.ts │ │ │ │ ├── repos-create-tag-protection.ts │ │ │ │ ├── repos-create-using-template.ts │ │ │ │ ├── repos-create-webhook.ts │ │ │ │ ├── repos-decline-invitation-for-authenticated-user.ts │ │ │ │ ├── repos-delete-access-restrictions.ts │ │ │ │ ├── repos-delete-admin-branch-protection.ts │ │ │ │ ├── repos-delete-an-environment.ts │ │ │ │ ├── repos-delete-autolink.ts │ │ │ │ ├── repos-delete-branch-protection.ts │ │ │ │ ├── repos-delete-commit-comment.ts │ │ │ │ ├── repos-delete-commit-signature-protection.ts │ │ │ │ ├── repos-delete-deploy-key.ts │ │ │ │ ├── repos-delete-deployment-branch-policy.ts │ │ │ │ ├── repos-delete-deployment.ts │ │ │ │ ├── repos-delete-file.ts │ │ │ │ ├── repos-delete-invitation.ts │ │ │ │ ├── repos-delete-org-ruleset.ts │ │ │ │ ├── repos-delete-pages-site.ts │ │ │ │ ├── repos-delete-pull-request-review-protection.ts │ │ │ │ ├── repos-delete-release-asset.ts │ │ │ │ ├── repos-delete-release.ts │ │ │ │ ├── repos-delete-repo-ruleset.ts │ │ │ │ ├── repos-delete-tag-protection.ts │ │ │ │ ├── repos-delete-webhook.ts │ │ │ │ ├── repos-delete.ts │ │ │ │ ├── repos-disable-automated-security-fixes.ts │ │ │ │ ├── repos-disable-deployment-protection-rule.ts │ │ │ │ ├── repos-disable-private-vulnerability-reporting.ts │ │ │ │ ├── repos-disable-vulnerability-alerts.ts │ │ │ │ ├── repos-download-tarball-archive.ts │ │ │ │ ├── repos-download-zipball-archive.ts │ │ │ │ ├── repos-enable-automated-security-fixes.ts │ │ │ │ ├── repos-enable-private-vulnerability-reporting.ts │ │ │ │ ├── repos-enable-vulnerability-alerts.ts │ │ │ │ ├── repos-generate-release-notes.ts │ │ │ │ ├── repos-get-access-restrictions.ts │ │ │ │ ├── repos-get-admin-branch-protection.ts │ │ │ │ ├── repos-get-all-deployment-protection-rules.ts │ │ │ │ ├── repos-get-all-environments.ts │ │ │ │ ├── repos-get-all-status-check-contexts.ts │ │ │ │ ├── repos-get-all-topics.ts │ │ │ │ ├── repos-get-apps-with-access-to-protected-branch.ts │ │ │ │ ├── repos-get-autolink.ts │ │ │ │ ├── repos-get-branch-protection.ts │ │ │ │ ├── repos-get-branch-rules.ts │ │ │ │ ├── repos-get-branch.ts │ │ │ │ ├── repos-get-clones.ts │ │ │ │ ├── repos-get-code-frequency-stats.ts │ │ │ │ ├── repos-get-collaborator-permission-level.ts │ │ │ │ ├── repos-get-combined-status-for-ref.ts │ │ │ │ ├── repos-get-commit-activity-stats.ts │ │ │ │ ├── repos-get-commit-comment.ts │ │ │ │ ├── repos-get-commit-signature-protection.ts │ │ │ │ ├── repos-get-commit.ts │ │ │ │ ├── repos-get-community-profile-metrics.ts │ │ │ │ ├── repos-get-content-json.ts │ │ │ │ ├── repos-get-content-vnd-github-object.ts │ │ │ │ ├── repos-get-contributors-stats.ts │ │ │ │ ├── repos-get-custom-deployment-protection-rule.ts │ │ │ │ ├── repos-get-deploy-key.ts │ │ │ │ ├── repos-get-deployment-branch-policy.ts │ │ │ │ ├── repos-get-deployment-status.ts │ │ │ │ ├── repos-get-deployment.ts │ │ │ │ ├── repos-get-environment.ts │ │ │ │ ├── repos-get-latest-pages-build.ts │ │ │ │ ├── repos-get-latest-release.ts │ │ │ │ ├── repos-get-org-ruleset.ts │ │ │ │ ├── repos-get-org-rulesets.ts │ │ │ │ ├── repos-get-pages-build.ts │ │ │ │ ├── repos-get-pages-health-check.ts │ │ │ │ ├── repos-get-pages.ts │ │ │ │ ├── repos-get-participation-stats.ts │ │ │ │ ├── repos-get-pull-request-review-protection.ts │ │ │ │ ├── repos-get-punch-card-stats.ts │ │ │ │ ├── repos-get-readme-in-directory.ts │ │ │ │ ├── repos-get-readme.ts │ │ │ │ ├── repos-get-release-asset.ts │ │ │ │ ├── repos-get-release-by-tag.ts │ │ │ │ ├── repos-get-release.ts │ │ │ │ ├── repos-get-repo-ruleset.ts │ │ │ │ ├── repos-get-repo-rulesets.ts │ │ │ │ ├── repos-get-status-checks-protection.ts │ │ │ │ ├── repos-get-teams-with-access-to-protected-branch.ts │ │ │ │ ├── repos-get-top-paths.ts │ │ │ │ ├── repos-get-top-referrers.ts │ │ │ │ ├── repos-get-users-with-access-to-protected-branch.ts │ │ │ │ ├── repos-get-views.ts │ │ │ │ ├── repos-get-webhook-config-for-repo.ts │ │ │ │ ├── repos-get-webhook-delivery.ts │ │ │ │ ├── repos-get-webhook.ts │ │ │ │ ├── repos-get.ts │ │ │ │ ├── repos-list-activities.ts │ │ │ │ ├── repos-list-autolinks.ts │ │ │ │ ├── repos-list-branches-for-head-commit.ts │ │ │ │ ├── repos-list-branches.ts │ │ │ │ ├── repos-list-collaborators.ts │ │ │ │ ├── repos-list-comments-for-commit.ts │ │ │ │ ├── repos-list-commit-comments-for-repo.ts │ │ │ │ ├── repos-list-commit-statuses-for-ref.ts │ │ │ │ ├── repos-list-commits.ts │ │ │ │ ├── repos-list-contributors.ts │ │ │ │ ├── repos-list-custom-deployment-rule-integrations.ts │ │ │ │ ├── repos-list-deploy-keys.ts │ │ │ │ ├── repos-list-deployment-branch-policies.ts │ │ │ │ ├── repos-list-deployment-statuses.ts │ │ │ │ ├── repos-list-deployments.ts │ │ │ │ ├── repos-list-for-authenticated-user.ts │ │ │ │ ├── repos-list-for-org.ts │ │ │ │ ├── repos-list-for-user.ts │ │ │ │ ├── repos-list-forks.ts │ │ │ │ ├── repos-list-invitations-for-authenticated-user.ts │ │ │ │ ├── repos-list-invitations.ts │ │ │ │ ├── repos-list-languages.ts │ │ │ │ ├── repos-list-pages-builds.ts │ │ │ │ ├── repos-list-public.ts │ │ │ │ ├── repos-list-pull-requests-associated-with-commit.ts │ │ │ │ ├── repos-list-release-assets.ts │ │ │ │ ├── repos-list-releases.ts │ │ │ │ ├── repos-list-tag-protection.ts │ │ │ │ ├── repos-list-tags.ts │ │ │ │ ├── repos-list-teams.ts │ │ │ │ ├── repos-list-webhook-deliveries.ts │ │ │ │ ├── repos-list-webhooks.ts │ │ │ │ ├── repos-merge-upstream.ts │ │ │ │ ├── repos-merge.ts │ │ │ │ ├── repos-ping-webhook.ts │ │ │ │ ├── repos-redeliver-webhook-delivery.ts │ │ │ │ ├── repos-remove-app-access-restrictions.ts │ │ │ │ ├── repos-remove-collaborator.ts │ │ │ │ ├── repos-remove-status-check-contexts.ts │ │ │ │ ├── repos-remove-status-check-protection.ts │ │ │ │ ├── repos-remove-team-access-restrictions.ts │ │ │ │ ├── repos-remove-user-access-restrictions.ts │ │ │ │ ├── repos-rename-branch.ts │ │ │ │ ├── repos-replace-all-topics.ts │ │ │ │ ├── repos-request-pages-build.ts │ │ │ │ ├── repos-set-admin-branch-protection.ts │ │ │ │ ├── repos-set-app-access-restrictions.ts │ │ │ │ ├── repos-set-status-check-contexts.ts │ │ │ │ ├── repos-set-team-access-restrictions.ts │ │ │ │ ├── repos-set-user-access-restrictions.ts │ │ │ │ ├── repos-test-push-webhook.ts │ │ │ │ ├── repos-transfer.ts │ │ │ │ ├── repos-update-branch-protection.ts │ │ │ │ ├── repos-update-commit-comment.ts │ │ │ │ ├── repos-update-deployment-branch-policy.ts │ │ │ │ ├── repos-update-information-about-pages-site.ts │ │ │ │ ├── repos-update-invitation.ts │ │ │ │ ├── repos-update-org-ruleset.ts │ │ │ │ ├── repos-update-pull-request-review-protection.ts │ │ │ │ ├── repos-update-release-asset.ts │ │ │ │ ├── repos-update-release.ts │ │ │ │ ├── repos-update-repo-ruleset.ts │ │ │ │ ├── repos-update-status-check-protection.ts │ │ │ │ ├── repos-update-webhook-config-for-repo.ts │ │ │ │ ├── repos-update-webhook.ts │ │ │ │ ├── repos-update.ts │ │ │ │ └── repos-upload-release-asset.ts │ │ │ ├── models.ts │ │ │ ├── models │ │ │ ├── activity.ts │ │ │ ├── author-association.ts │ │ │ ├── auto-merge.ts │ │ │ ├── autolink.ts │ │ │ ├── basic-error.ts │ │ │ ├── branch-protection.ts │ │ │ ├── branch-restriction-policy.ts │ │ │ ├── branch-short.ts │ │ │ ├── branch-with-protection.ts │ │ │ ├── check-automated-security-fixes.ts │ │ │ ├── clone-traffic.ts │ │ │ ├── code-frequency-stat.ts │ │ │ ├── code-of-conduct-simple.ts │ │ │ ├── code-of-conduct.ts │ │ │ ├── codeowners-errors.ts │ │ │ ├── collaborator.ts │ │ │ ├── combined-commit-status.ts │ │ │ ├── commit-activity.ts │ │ │ ├── commit-comment.ts │ │ │ ├── commit-comparison.ts │ │ │ ├── commit.ts │ │ │ ├── community-profile.ts │ │ │ ├── content-directory.ts │ │ │ ├── content-file.ts │ │ │ ├── content-submodule.ts │ │ │ ├── content-symlink.ts │ │ │ ├── content-traffic.ts │ │ │ ├── content-tree.ts │ │ │ ├── contributor-activity.ts │ │ │ ├── contributor.ts │ │ │ ├── custom-deployment-rule-app.ts │ │ │ ├── deploy-key.ts │ │ │ ├── deployment-branch-policy-name-pattern.ts │ │ │ ├── deployment-branch-policy-settings.ts │ │ │ ├── deployment-branch-policy.ts │ │ │ ├── deployment-protection-rule.ts │ │ │ ├── deployment-reviewer-type.ts │ │ │ ├── deployment-status.ts │ │ │ ├── deployment.ts │ │ │ ├── diff-entry.ts │ │ │ ├── empty-object.ts │ │ │ ├── environment.ts │ │ │ ├── file-commit.ts │ │ │ ├── full-repository.ts │ │ │ ├── hook-delivery-item.ts │ │ │ ├── hook-delivery.ts │ │ │ ├── hook-response.ts │ │ │ ├── hook.ts │ │ │ ├── integration.ts │ │ │ ├── language.ts │ │ │ ├── link.ts │ │ │ ├── merged-upstream.ts │ │ │ ├── minimal-repository.ts │ │ │ ├── nullable-code-of-conduct-simple.ts │ │ │ ├── nullable-collaborator.ts │ │ │ ├── nullable-community-health-file.ts │ │ │ ├── nullable-git-user.ts │ │ │ ├── nullable-integration.ts │ │ │ ├── nullable-license-simple.ts │ │ │ ├── nullable-milestone.ts │ │ │ ├── nullable-repository.ts │ │ │ ├── nullable-simple-user.ts │ │ │ ├── nullable-team-simple.ts │ │ │ ├── org-ruleset-conditions.ts │ │ │ ├── page-build-status.ts │ │ │ ├── page-build.ts │ │ │ ├── page-deployment.ts │ │ │ ├── page.ts │ │ │ ├── pages-health-check.ts │ │ │ ├── pages-https-certificate.ts │ │ │ ├── pages-source-hash.ts │ │ │ ├── participation-stats.ts │ │ │ ├── protected-branch-admin-enforced.ts │ │ │ ├── protected-branch-pull-request-review.ts │ │ │ ├── protected-branch-required-status-check.ts │ │ │ ├── protected-branch.ts │ │ │ ├── pull-request-simple.ts │ │ │ ├── reaction-rollup.ts │ │ │ ├── referrer-traffic.ts │ │ │ ├── release-asset.ts │ │ │ ├── release-notes-content.ts │ │ │ ├── release.ts │ │ │ ├── repository-collaborator-permission.ts │ │ │ ├── repository-invitation.ts │ │ │ ├── repository-rule-branch-name-pattern.ts │ │ │ ├── repository-rule-commit-author-email-pattern.ts │ │ │ ├── repository-rule-commit-message-pattern.ts │ │ │ ├── repository-rule-committer-email-pattern.ts │ │ │ ├── repository-rule-creation.ts │ │ │ ├── repository-rule-deletion.ts │ │ │ ├── repository-rule-detailed.ts │ │ │ ├── repository-rule-enforcement.ts │ │ │ ├── repository-rule-non-fast-forward.ts │ │ │ ├── repository-rule-params-status-check-configuration.ts │ │ │ ├── repository-rule-pull-request.ts │ │ │ ├── repository-rule-required-deployments.ts │ │ │ ├── repository-rule-required-linear-history.ts │ │ │ ├── repository-rule-required-signatures.ts │ │ │ ├── repository-rule-required-status-checks.ts │ │ │ ├── repository-rule-ruleset-info.ts │ │ │ ├── repository-rule-tag-name-pattern.ts │ │ │ ├── repository-rule-update.ts │ │ │ ├── repository-rule.ts │ │ │ ├── repository-ruleset-bypass-actor.ts │ │ │ ├── repository-ruleset-conditions-repository-id-target.ts │ │ │ ├── repository-ruleset-conditions-repository-name-target.ts │ │ │ ├── repository-ruleset-conditions.ts │ │ │ ├── repository-ruleset.ts │ │ │ ├── repository.ts │ │ │ ├── scim-error.ts │ │ │ ├── security-and-analysis.ts │ │ │ ├── short-branch.ts │ │ │ ├── simple-commit-status.ts │ │ │ ├── simple-user.ts │ │ │ ├── status-check-policy.ts │ │ │ ├── status.ts │ │ │ ├── tag-protection.ts │ │ │ ├── tag.ts │ │ │ ├── team.ts │ │ │ ├── topic.ts │ │ │ ├── traffic.ts │ │ │ ├── validation-error-simple.ts │ │ │ ├── validation-error.ts │ │ │ ├── verification.ts │ │ │ ├── view-traffic.ts │ │ │ ├── wait-timer.ts │ │ │ ├── webhook-config-content-type.ts │ │ │ ├── webhook-config-insecure-ssl.ts │ │ │ ├── webhook-config-secret.ts │ │ │ ├── webhook-config-url.ts │ │ │ └── webhook-config.ts │ │ │ ├── request-builder.ts │ │ │ ├── services.ts │ │ │ ├── services │ │ │ └── repos.service.ts │ │ │ └── strict-http-response.ts │ │ ├── guards │ │ └── dirty-form.guard.ts │ │ ├── models │ │ ├── asset.model.ts │ │ ├── content-history.model.ts │ │ ├── content.model.ts │ │ ├── locale.model.ts │ │ ├── material.model.ts │ │ ├── me.model.ts │ │ ├── schema.model.ts │ │ ├── settings.model.ts │ │ ├── space.model.ts │ │ ├── task.model.ts │ │ ├── token.model.ts │ │ ├── translate.model.ts │ │ ├── translation-history.model.ts │ │ ├── translation.model.ts │ │ ├── unsplash-plugin.model.ts │ │ └── user.model.ts │ │ ├── pipes │ │ ├── can-user-perform.pipe.ts │ │ ├── digital-store.pipe.ts │ │ └── time-duration.pipe.ts │ │ ├── services │ │ ├── asset.service.ts │ │ ├── content-helper.service.ts │ │ ├── content-history.service.ts │ │ ├── content.service.ts │ │ ├── locale.service.ts │ │ ├── material.service.ts │ │ ├── me.service.ts │ │ ├── notification.service.spec.ts │ │ ├── notification.service.ts │ │ ├── open-api.service.ts │ │ ├── schema.service.ts │ │ ├── settings.service.ts │ │ ├── space.service.ts │ │ ├── task.service.ts │ │ ├── token.service.ts │ │ ├── translate.service.ts │ │ ├── translation-history.service.ts │ │ ├── translation.service.ts │ │ ├── unsplash-plugin.service.ts │ │ └── user.service.ts │ │ ├── stores │ │ ├── app-settings.store.ts │ │ ├── local-settings.store.ts │ │ ├── space.store.ts │ │ └── user.store.ts │ │ └── validators │ │ ├── asset.validator.ts │ │ ├── common.validator.ts │ │ ├── content.validator.ts │ │ ├── locale.validator.ts │ │ ├── schema.validator.ts │ │ ├── settings.validator.ts │ │ ├── space.validator.ts │ │ ├── token.validator.ts │ │ └── translation.validator.ts ├── apple-touch-icon.png ├── assets │ ├── .gitkeep │ ├── account_circle.svg │ ├── cloud_upload.svg │ ├── icons │ │ ├── audio_file.svg │ │ ├── description.svg │ │ ├── file_present.svg │ │ ├── folder.svg │ │ ├── font_download.svg │ │ ├── image.svg │ │ └── video_file.svg │ ├── logo-adaptive.svg │ ├── logo-black.svg │ ├── logo-white.svg │ ├── logo.png │ └── material-icons.json ├── environments │ ├── env.ts │ ├── environment.docker.ts │ ├── environment.prod.ts │ └── environment.ts ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── scripts │ └── sync-v1.js ├── site.webmanifest ├── styles.scss ├── styles │ ├── _background.scss │ ├── _layout.scss │ ├── _markdown.scss │ ├── _mat-card.scss │ ├── _mat-dialog.scss │ ├── _mat-grid-list.scss │ ├── _mat-list.scss │ ├── _mat-menu.scss │ ├── _mat-paginator.scss │ ├── _mat-snack-bar.scss │ ├── _mat-table.scss │ ├── _mat-toolbar-theme.scss │ ├── _mat-toolbar.scss │ ├── _rich-text-editor.scss │ ├── highlightjs │ │ ├── _dark.scss │ │ └── _light.scss │ └── styles-variables.scss └── test.ts ├── storage.rules ├── tailwind.config.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.script.json └── tsconfig.spec.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | 9 | max_line_length = 140 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.ts] 14 | quote_type = single 15 | ij_typescript_indent_size = 2 16 | ij_typescript_tab_width = 2 17 | ij_typescript_continuation_indent_size = 2 18 | ij_typescript_use_double_quotes = false 19 | ij_typescript_import_sort_members = true 20 | ij_typescript_import_sort_module_name = true 21 | ij_typescript_import_merge_members = true 22 | 23 | [*.html] 24 | ij_html_quote_style = double 25 | 26 | [*.md] 27 | max_line_length = off 28 | trim_trailing_whitespace = false 29 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | /tmp 6 | /out-tsc 7 | build 8 | coverage 9 | 10 | 11 | # dependencies 12 | /node_modules 13 | 14 | # IDEs and editors 15 | debug.log 16 | *.iml 17 | /.idea 18 | .project 19 | .classpath 20 | .c9/ 21 | *.launch 22 | .settings/ 23 | *.sublime-workspace 24 | 25 | # IDE - VSCode 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | 32 | # misc 33 | /.angular/cache 34 | /.sass-cache 35 | /.eslintrc 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | 48 | #Lock files 49 | package-lock.json 50 | yarn.lock 51 | 52 | # Generated 53 | src/app/shared/generated/ 54 | firebase-export* 55 | 56 | .github 57 | api-docs 58 | 59 | functions 60 | 61 | # Tests 62 | /**/*.spec.ts 63 | src/test.ts 64 | src/environments/* 65 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "demo-localess-dev" 4 | }, 5 | "targets": { 6 | "demo-localess-dev": { 7 | "hosting": { 8 | "localess": [ 9 | "demo-localess-dev" 10 | ] 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [Lessify] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | 5 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.github/workflows/unit-test.yml: -------------------------------------------------------------------------------- 1 | name: Run Unit Tests 2 | 3 | on: 4 | push: 5 | branches: [ main, develop ] 6 | pull_request: 7 | branches: [ main, develop ] 8 | 9 | jobs: 10 | build: 11 | name: Lint and Build 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | - uses: actions/setup-node@v4 18 | with: 19 | node-version: 20 20 | cache: npm 21 | - run: npm ci 22 | - run: npm --prefix functions install 23 | - run: npm run lint 24 | # - run: npm run prettier 25 | - run: npm run build 26 | - run: npm --prefix functions run build 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | #NX 10 | .nx/* 11 | 12 | # Node 13 | /node_modules 14 | npm-debug.log 15 | yarn-error.log 16 | 17 | # IDEs and editors 18 | .idea/ 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # Visual Studio Code 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # Miscellaneous 35 | /.angular/cache 36 | .sass-cache/ 37 | /connect.lock 38 | /coverage 39 | /libpeerconnection.log 40 | testem.log 41 | /typings 42 | 43 | # System files 44 | .DS_Store 45 | Thumbs.db 46 | 47 | # Logs 48 | *.log 49 | 50 | # Firebase 51 | .firebase 52 | *-debug.log 53 | .runtimeconfig.json 54 | firebase-export 55 | firebase-export-* 56 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | build 3 | coverage 4 | .github 5 | api-docs 6 | .vscode 7 | firebase-export* 8 | node_modules 9 | dist 10 | package-lock.json 11 | 12 | src/app/shared/generated/ 13 | 14 | functions 15 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "singleQuote": true, 5 | "semi": true, 6 | "bracketSpacing": true, 7 | "arrowParens": "avoid", 8 | "trailingComma": "all", 9 | "bracketSameLine": true, 10 | "printWidth": 140, 11 | "proseWrap": "always", 12 | "htmlWhitespaceSensitivity": "strict", 13 | "endOfLine": "auto", 14 | "overrides": [ 15 | { 16 | "files": "*.component.html", 17 | "options": { 18 | "parser": "angular" 19 | } 20 | }, 21 | { 22 | "files": "*.scss", 23 | "options": { 24 | "parser": "scss" 25 | } 26 | }, 27 | { 28 | "files": "*.html", 29 | "options": { 30 | "parser": "html" 31 | } 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine3.18 AS app-env 2 | 3 | # Install Python and Java and pre-cache emulator dependencies. 4 | RUN apk add --no-cache python3 py3-pip openjdk11-jre bash && \ 5 | npm install -g firebase-tools && \ 6 | firebase setup:emulators:firestore && \ 7 | firebase setup:emulators:database && \ 8 | firebase setup:emulators:pubsub && \ 9 | firebase setup:emulators:storage && \ 10 | firebase setup:emulators:ui && \ 11 | rm -rf /var/cache/apk/* 12 | 13 | WORKDIR /app 14 | 15 | COPY . . 16 | ## UI 17 | RUN npm install 18 | RUN npm run build:docker 19 | ## Functions 20 | RUN npm --prefix functions install 21 | RUN npm --prefix functions run build 22 | 23 | CMD ["npm", "run", "emulator"] 24 | -------------------------------------------------------------------------------- /cors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "origin": ["*"], 4 | "method": ["GET", "HEAD"], 5 | "maxAgeSeconds": 3600 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /functions/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | es6: true, 5 | node: true, 6 | }, 7 | extends: [ 8 | 'eslint:recommended', 9 | 'plugin:import/errors', 10 | 'plugin:import/warnings', 11 | 'plugin:import/typescript', 12 | 'google', 13 | 'plugin:@typescript-eslint/recommended', 14 | 'plugin:prettier/recommended', 15 | ], 16 | parser: '@typescript-eslint/parser', 17 | parserOptions: { 18 | project: ['tsconfig.json', 'tsconfig.dev.json'], 19 | sourceType: 'module', 20 | }, 21 | ignorePatterns: [ 22 | '/lib/**/*', // Ignore built files. 23 | ], 24 | plugins: ['@typescript-eslint', 'import'], 25 | rules: { 26 | quotes: ['error', 'single'], 27 | 'import/no-unresolved': 0, 28 | indent: ['error', 2], 29 | 'max-len': ['error', { code: 180 }], 30 | 'linebreak-style': 0, 31 | 'prettier/prettier': [ 32 | 'error', 33 | { 34 | endOfLine: 'auto', 35 | }, 36 | ], 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /functions/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled JavaScript files 2 | lib/ 3 | 4 | # TypeScript v1 declaration files 5 | typings/ 6 | 7 | # Node.js dependency directory 8 | node_modules/ 9 | 10 | # ENV 11 | .env.local 12 | -------------------------------------------------------------------------------- /functions/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | build 3 | coverage 4 | node_modules 5 | lib 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /functions/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "useTabs": false, 4 | "singleQuote": true, 5 | "semi": true, 6 | "bracketSpacing": true, 7 | "arrowParens": "avoid", 8 | "trailingComma": "es5", 9 | "bracketSameLine": true, 10 | "printWidth": 140, 11 | "endOfLine": "auto" 12 | } 13 | -------------------------------------------------------------------------------- /functions/src/index.ts: -------------------------------------------------------------------------------- 1 | import { setGlobalOptions } from 'firebase-functions/v2'; 2 | 3 | setGlobalOptions({ 4 | timeoutSeconds: 540, 5 | region: 'europe-west6', 6 | concurrency: 600, 7 | cpu: 1, 8 | }); 9 | 10 | export { asset } from './assets'; 11 | 12 | export { content } from './contents'; 13 | 14 | export { openapi } from './open-api'; 15 | 16 | export { setup } from './setup'; 17 | 18 | export { space } from './spaces'; 19 | 20 | export { storage } from './storage'; 21 | 22 | export { task } from './tasks'; 23 | 24 | export { translate } from './translate'; 25 | 26 | export { translation } from './translations'; 27 | 28 | export { user } from './users'; 29 | 30 | export { v1 as publicv1 } from './v1'; 31 | 32 | // Plugins API 33 | export { unsplash } from './plugins/unsplash/api'; 34 | -------------------------------------------------------------------------------- /functions/src/models/asset.zod.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { AssetKind } from './asset.model'; 3 | 4 | export const assetBaseSchema = z.object({ 5 | id: z.string(), 6 | kind: z.nativeEnum(AssetKind), 7 | name: z.string(), 8 | parentPath: z.string(), 9 | }); 10 | 11 | export const assetFolderSchema = assetBaseSchema.extend({ 12 | kind: z.literal(AssetKind.FOLDER), 13 | }); 14 | 15 | export const assetMetadataSchema = z.object({ 16 | format: z.string().optional(), 17 | width: z.number().optional(), 18 | height: z.number().optional(), 19 | }); 20 | 21 | export const assetFileSchema = assetBaseSchema.extend({ 22 | kind: z.literal(AssetKind.FILE), 23 | extension: z.string(), 24 | type: z.string(), 25 | size: z.number(), 26 | alt: z.string().optional(), 27 | metadata: assetMetadataSchema.optional(), 28 | source: z.string().optional(), 29 | }); 30 | 31 | export const assetSchema = z.union([assetFileSchema, assetFolderSchema]); 32 | 33 | export const zAssetExportArraySchema = z.array(assetSchema); 34 | -------------------------------------------------------------------------------- /functions/src/models/content.zod.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { ContentKind } from './content.model'; 3 | 4 | export const contentDataSchema = z.object({ 5 | _id: z.string(), 6 | _schema: z.string().optional(), 7 | schema: z.string(), 8 | }); 9 | 10 | export const contentBaseSchema = z.object({ 11 | id: z.string(), 12 | kind: z.nativeEnum(ContentKind), 13 | name: z.string(), 14 | slug: z.string(), 15 | parentSlug: z.string(), 16 | fullSlug: z.string(), 17 | }); 18 | 19 | export const contentDocumentSchema = contentBaseSchema.extend({ 20 | kind: z.literal(ContentKind.DOCUMENT), 21 | schema: z.string(), 22 | data: z.string().optional().or(contentDataSchema.optional()), 23 | }); 24 | 25 | export const contentFolderSchema = contentBaseSchema.extend({ 26 | kind: z.literal(ContentKind.FOLDER), 27 | }); 28 | 29 | export const contentSchema = z.union([contentDocumentSchema, contentFolderSchema]); 30 | 31 | export const zContentExportArraySchema = z.array(contentSchema); 32 | -------------------------------------------------------------------------------- /functions/src/models/firebase.model.ts: -------------------------------------------------------------------------------- 1 | export const FIREBASE_CONFIG = 'FIREBASE_CONFIG'; 2 | 3 | export interface FirebaseConfig { 4 | projectId: string; 5 | storageBucket: string; 6 | locationId?: string; 7 | } 8 | -------------------------------------------------------------------------------- /functions/src/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './asset.model'; 2 | export * from './asset.zod'; 3 | export * from './content.model'; 4 | export * from './content.zod'; 5 | export * from './content-history.model'; 6 | export * from './firebase.model'; 7 | export * from './locale.model'; 8 | export * from './open-api.model'; 9 | export * from './schema.model'; 10 | export * from './schema.zod'; 11 | export * from './space.model'; 12 | export * from './task.model'; 13 | export * from './token.model'; 14 | export * from './translate.model'; 15 | export * from './translation.model'; 16 | export * from './translation.zod'; 17 | export * from './translation-history.model'; 18 | export * from './user.model'; 19 | -------------------------------------------------------------------------------- /functions/src/models/locale.model.ts: -------------------------------------------------------------------------------- 1 | export interface Locale { 2 | id: string; 3 | name: string; 4 | } 5 | -------------------------------------------------------------------------------- /functions/src/models/open-api.model.ts: -------------------------------------------------------------------------------- 1 | export interface GenerateOpenApiData { 2 | spaceId: string; 3 | } 4 | -------------------------------------------------------------------------------- /functions/src/models/space.model.ts: -------------------------------------------------------------------------------- 1 | import { Timestamp } from 'firebase-admin/firestore'; 2 | import { Locale } from './locale.model'; 3 | 4 | export const DEFAULT_LOCALE: Locale = { id: 'en', name: 'English' }; 5 | 6 | export interface Space { 7 | name: string; 8 | locales: Locale[]; 9 | localeFallback: Locale; 10 | // overview 11 | overview?: SpaceOverview; 12 | progress?: ProgressOverview; 13 | // timestamp 14 | createdAt: Timestamp; 15 | updatedAt: Timestamp; 16 | } 17 | 18 | export interface SpaceOverviewData { 19 | spaceId: string; 20 | } 21 | 22 | export interface SpaceOverview { 23 | translationsCount: number; 24 | translationsSize: number; 25 | assetsCount: number; 26 | assetsSize: number; 27 | contentsCount: number; 28 | contentsSize: number; 29 | schemasCount: number; 30 | tasksCount: number; 31 | tasksSize: number; 32 | totalSize: number; 33 | updatedAt: Timestamp; 34 | } 35 | 36 | export interface ProgressOverview { 37 | translations: Record; 38 | } 39 | -------------------------------------------------------------------------------- /functions/src/models/token.model.ts: -------------------------------------------------------------------------------- 1 | export interface Token { 2 | id: string; 3 | name: string; 4 | } 5 | -------------------------------------------------------------------------------- /functions/src/models/translate.model.ts: -------------------------------------------------------------------------------- 1 | export interface TranslateData { 2 | content: string; 3 | sourceLocale: string | null; 4 | targetLocale: string; 5 | } 6 | -------------------------------------------------------------------------------- /functions/src/models/translation.model.ts: -------------------------------------------------------------------------------- 1 | import { Timestamp } from 'firebase-admin/firestore'; 2 | 3 | export enum TranslationType { 4 | STRING = 'STRING', 5 | PLURAL = 'PLURAL', 6 | ARRAY = 'ARRAY', 7 | } 8 | 9 | export interface Translation { 10 | type: TranslationType; 11 | locales: Record; 12 | labels?: string[]; 13 | autoTranslate?: boolean; 14 | description?: string; 15 | updatedBy?: { 16 | name: string; 17 | email: string; 18 | }; 19 | createdAt: Timestamp; 20 | updatedAt: Timestamp; 21 | } 22 | 23 | export interface PublishTranslationsData { 24 | spaceId: string; 25 | } 26 | 27 | // Import and Export 28 | export interface TranslationExport extends Omit { 29 | id: string; 30 | } 31 | -------------------------------------------------------------------------------- /functions/src/models/translation.zod.ts: -------------------------------------------------------------------------------- 1 | import { TranslationType } from './translation.model'; 2 | import { z } from 'zod'; 3 | 4 | // const ID_PATTERN = /^[a-zA-Z]+[a-zA-Z0-9-_.]*[a-zA-Z0-9]+$/; 5 | 6 | export const translationSchema = z.object({ 7 | id: z.string(), 8 | type: z.nativeEnum(TranslationType), 9 | locales: z.record(z.string(), z.string()), 10 | labels: z.array(z.string()).optional(), 11 | description: z.string().optional(), 12 | }); 13 | 14 | export const zTranslationExportArraySchema = z.array(translationSchema); 15 | 16 | export const zTranslationFlatExportSchema = z.record(z.string(), z.string()); 17 | -------------------------------------------------------------------------------- /functions/src/services/content-history.service.ts: -------------------------------------------------------------------------------- 1 | import { firestoreService } from '../config'; 2 | import { CollectionReference, DocumentReference } from 'firebase-admin/firestore'; 3 | 4 | /** 5 | * find Content History by ID 6 | * @param {string} spaceId Space identifier 7 | * @param {string} contentId Content identifier 8 | * @param {string} id Content identifier 9 | * @return {DocumentReference} document reference to the space 10 | */ 11 | export function findContentHistoryById(spaceId: string, contentId: string, id: string): DocumentReference { 12 | return firestoreService.doc(`spaces/${spaceId}/contents/${contentId}/histories/${id}`); 13 | } 14 | 15 | /** 16 | * find Contents History 17 | * @param {string} spaceId Space identifier 18 | * @param {string} contentId Content identifier 19 | * @return {DocumentReference} document reference to the space 20 | */ 21 | export function findContentsHistory(spaceId: string, contentId: string): CollectionReference { 22 | return firestoreService.collection(`spaces/${spaceId}/contents/${contentId}/histories`); 23 | } 24 | -------------------------------------------------------------------------------- /functions/src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './asset.service'; 2 | export * from './content.service'; 3 | export * from './content-history.service'; 4 | export * from './open-api.service'; 5 | export * from './schema.service'; 6 | export * from './space.service'; 7 | export * from './task.service'; 8 | export * from './token.service'; 9 | export * from './translation.service'; 10 | export * from './translation-history.service'; 11 | export * from './user.service'; 12 | -------------------------------------------------------------------------------- /functions/src/services/schema.service.ts: -------------------------------------------------------------------------------- 1 | import { firestoreService } from '../config'; 2 | import { DocumentReference, Query, Timestamp } from 'firebase-admin/firestore'; 3 | 4 | /** 5 | * find Schema by ID 6 | * @param {string} spaceId Space identifier 7 | * @param {string} id Content identifier 8 | * @return {DocumentReference} document reference to the space 9 | */ 10 | export function findSchemaById(spaceId: string, id: string): DocumentReference { 11 | return firestoreService.doc(`spaces/${spaceId}/schemas/${id}`); 12 | } 13 | 14 | /** 15 | * find Contents 16 | * @param {string} spaceId Space identifier 17 | * @param {number} fromDate Space identifier 18 | * @return {Query} collection 19 | */ 20 | export function findSchemas(spaceId: string, fromDate?: number): Query { 21 | let assetsRef: Query = firestoreService.collection(`spaces/${spaceId}/schemas`); 22 | if (fromDate) { 23 | assetsRef = assetsRef.where('updatedAt', '>=', Timestamp.fromMillis(fromDate)); 24 | } 25 | return assetsRef; 26 | } 27 | -------------------------------------------------------------------------------- /functions/src/services/task.service.ts: -------------------------------------------------------------------------------- 1 | import { firestoreService } from '../config'; 2 | import { CollectionReference, DocumentReference } from 'firebase-admin/firestore'; 3 | 4 | /** 5 | * find Tasks 6 | * @param {string} spaceId Space identifier 7 | * @return {DocumentReference} document reference to the space 8 | */ 9 | export function findTasks(spaceId: string): CollectionReference { 10 | return firestoreService.collection(`spaces/${spaceId}/tasks`); 11 | } 12 | 13 | /** 14 | * find Task by ID 15 | * @param {string} spaceId Space identifier 16 | * @param {string} id Task identifier 17 | * @return {DocumentReference} document reference to the space 18 | */ 19 | export function findTaskById(spaceId: string, id: string): DocumentReference { 20 | return firestoreService.doc(`spaces/${spaceId}/tasks/${id}`); 21 | } 22 | -------------------------------------------------------------------------------- /functions/src/services/translation-history.service.ts: -------------------------------------------------------------------------------- 1 | import { firestoreService } from '../config'; 2 | import { CollectionReference, DocumentReference } from 'firebase-admin/firestore'; 3 | 4 | /** 5 | * find Translation History by ID 6 | * @param {string} spaceId Space identifier 7 | * @param {string} id Content identifier 8 | * @return {DocumentReference} document reference to the space 9 | */ 10 | export function findTranslationHistoryById(spaceId: string, id: string): DocumentReference { 11 | return firestoreService.doc(`spaces/${spaceId}/translations_history/${id}`); 12 | } 13 | 14 | /** 15 | * find Tasks 16 | * @param {string} spaceId Space identifier 17 | * @return {DocumentReference} document reference to the space 18 | */ 19 | export function findTranslationsHistory(spaceId: string): CollectionReference { 20 | return firestoreService.collection(`spaces/${spaceId}/translations_history`); 21 | } 22 | -------------------------------------------------------------------------------- /functions/src/services/translation.service.ts: -------------------------------------------------------------------------------- 1 | import { firestoreService } from '../config'; 2 | import { DocumentReference, Query, Timestamp } from 'firebase-admin/firestore'; 3 | 4 | /** 5 | * find Translation by ID 6 | * @param {string} spaceId Space identifier 7 | * @param {string} id Content identifier 8 | * @return {DocumentReference} document reference to the space 9 | */ 10 | export function findTranslationById(spaceId: string, id: string): DocumentReference { 11 | return firestoreService.doc(`spaces/${spaceId}/translations/${id}`); 12 | } 13 | 14 | /** 15 | * find Translations 16 | * @param {string} spaceId Space identifier 17 | * @param {number} fromDate Space identifier 18 | * @return {Query} collection 19 | */ 20 | export function findTranslations(spaceId: string, fromDate?: number): Query { 21 | let translationsRef: Query = firestoreService.collection(`spaces/${spaceId}/translations`); 22 | if (fromDate) { 23 | translationsRef = translationsRef.where('updatedAt', '>=', Timestamp.fromMillis(fromDate)); 24 | } 25 | return translationsRef; 26 | } 27 | -------------------------------------------------------------------------------- /functions/src/services/user.service.ts: -------------------------------------------------------------------------------- 1 | import { firestoreService } from '../config'; 2 | import { CollectionReference, DocumentReference } from 'firebase-admin/firestore'; 3 | 4 | /** 5 | * find Users 6 | * @return {DocumentReference} document reference to the space 7 | */ 8 | export function findUsers(): CollectionReference { 9 | return firestoreService.collection('users'); 10 | } 11 | 12 | /** 13 | * find User by ID 14 | * @param {string} id Task identifier 15 | * @return {DocumentReference} document reference to the space 16 | */ 17 | export function findUserById(id: string): DocumentReference { 18 | return firestoreService.doc(`users/${id}`); 19 | } 20 | -------------------------------------------------------------------------------- /functions/src/storage.ts: -------------------------------------------------------------------------------- 1 | import { logger } from 'firebase-functions/v2'; 2 | import { onObjectFinalized } from 'firebase-functions/v2/storage'; 3 | import { updateMetadataByPath } from './services'; 4 | 5 | const onFileUpload = onObjectFinalized(async event => { 6 | logger.info(`[Storage::onFileUpload] name : ${event.data.name}`); 7 | // logger.info(event.data); 8 | const { name } = event.data; 9 | // Spaces Assets 10 | // spaces/eo42RwNL8XHD7Cdvd8eO/assets/RpMDPKkmDM66Vc1jgDpo/original 11 | if (name && name.startsWith('spaces/') && name.includes('assets') && name.endsWith('/original')) { 12 | const assetPath = name.slice(0, -9); // remove '/original' 13 | await updateMetadataByPath(assetPath); 14 | } 15 | return; 16 | }); 17 | 18 | export const storage = { 19 | onupload: onFileUpload, 20 | }; 21 | -------------------------------------------------------------------------------- /functions/src/translate.ts: -------------------------------------------------------------------------------- 1 | import { logger } from 'firebase-functions/v2'; 2 | import { HttpsError, onCall } from 'firebase-functions/v2/https'; 3 | import { canPerform } from './utils/security-utils'; 4 | import { TranslateData, UserPermission } from './models'; 5 | import { translateCloud } from './services/translate.service'; 6 | import { isEmulatorEnabled } from './config'; 7 | 8 | export const translate = onCall(async request => { 9 | logger.info('[translate] data: ' + JSON.stringify(request.data)); 10 | logger.info('[translate] context.auth: ' + JSON.stringify(request.auth)); 11 | const { content, sourceLocale, targetLocale } = request.data; 12 | if (!canPerform(UserPermission.TRANSLATION_UPDATE, request.auth) || !canPerform(UserPermission.CONTENT_UPDATE, request.auth)) { 13 | throw new HttpsError('permission-denied', 'permission-denied'); 14 | } 15 | if (isEmulatorEnabled) { 16 | return `${content} : ${sourceLocale} -> ${targetLocale}`; 17 | } else { 18 | return await translateCloud(content, sourceLocale, targetLocale); 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /functions/tsconfig.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [".eslintrc.js"] 3 | } 4 | -------------------------------------------------------------------------------- /functions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "noImplicitReturns": true, 5 | "noUnusedLocals": true, 6 | "outDir": "lib", 7 | "sourceMap": true, 8 | "strict": true, 9 | "target": "ES2020", 10 | "esModuleInterop": true, 11 | "resolveJsonModule": true 12 | }, 13 | "compileOnSave": true, 14 | "include": [ 15 | "src" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /proxy.conf.js: -------------------------------------------------------------------------------- 1 | const PROXY_CONFIG = [ 2 | { 3 | context: ['/api'], 4 | target: 'http://127.0.0.1:5000', 5 | secure: false, 6 | logLevel: 'debug', 7 | changeOrigin: true, 8 | }, 9 | ]; 10 | module.exports = PROXY_CONFIG; 11 | -------------------------------------------------------------------------------- /remoteconfig.template.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /scripts/sync-v1.css: -------------------------------------------------------------------------------- 1 | [data-ll-id], [data-ll-field] { 2 | outline: 2px dashed rgba(0,92,187,0.5); 3 | transition: box-shadow ease-out 150ms; 4 | display: block; 5 | } 6 | 7 | [data-ll-id]:hover, [data-ll-field]:hover { 8 | box-shadow: inset 100vi 100vh rgba(0,92,187,0.1); 9 | outline: 2px solid rgba(0,92,187,1); 10 | cursor: pointer; 11 | } 12 | 13 | .ll-snackbar-container { 14 | position: fixed; 15 | bottom: 20px; 16 | display: flex; 17 | flex-direction: column-reverse; 18 | left: 50%; 19 | gap: 10px; 20 | } 21 | 22 | .ll-snackbar { 23 | min-width: 250px; 24 | background-color: #333; 25 | color: #fff; 26 | text-align: center; 27 | border-radius: 4px; 28 | padding: 16px; 29 | transform: translateX(-50%); 30 | box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16); 31 | animation: ll-fadein 0.5s, ll-fadeout 0.5s 2.5s; 32 | } 33 | 34 | @keyframes ll-fadein { 35 | from {bottom: 0; opacity: 0;} 36 | to {bottom: 30px; opacity: 1;} 37 | } 38 | 39 | @keyframes ll-fadeout { 40 | from {bottom: 30px; opacity: 1;} 41 | to {bottom: 0; opacity: 0;} 42 | } 43 | -------------------------------------------------------------------------------- /src/_app-theme.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | @use './app/features/features-theme'; 4 | @use './styles/mat-toolbar-theme'; 5 | 6 | // Styles for the docs app that are based on the current theme. 7 | @mixin theme($theme) { 8 | @include mat-toolbar-theme.theme($theme); 9 | @include features-theme.theme($theme); 10 | } 11 | -------------------------------------------------------------------------------- /src/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/app/app.component.scss -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Analytics } from '@angular/fire/analytics'; 3 | import { Performance } from '@angular/fire/performance'; 4 | import { MatIconRegistry } from '@angular/material/icon'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | @Component({ 8 | selector: 'll-root', 9 | templateUrl: './app.component.html', 10 | styleUrls: ['./app.component.scss'], 11 | imports: [RouterModule], 12 | }) 13 | export class AppComponent { 14 | constructor( 15 | private readonly performance: Performance, 16 | private readonly analytics: Analytics, 17 | private readonly iconRegistry: MatIconRegistry, 18 | ) { 19 | iconRegistry.setDefaultFontSetClass('material-symbols-outlined'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { HTTP_INTERCEPTORS } from '@angular/common/http'; 2 | import { ErrorHandler, NgModule, Optional, SkipSelf } from '@angular/core'; 3 | import { TitleStrategy } from '@angular/router'; 4 | 5 | import { AppErrorHandler } from './error-handler/app-error-handler.service'; 6 | import { HttpErrorInterceptor } from './http-interceptors/http-error.interceptor'; 7 | import { PageTitleStrategy } from './title/page-title.strategy'; 8 | 9 | @NgModule({ 10 | declarations: [], 11 | exports: [], 12 | imports: [], 13 | providers: [ 14 | { provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }, 15 | { provide: ErrorHandler, useClass: AppErrorHandler }, 16 | { provide: TitleStrategy, useClass: PageTitleStrategy }, 17 | ], 18 | }) 19 | export class CoreModule { 20 | constructor( 21 | @Optional() 22 | @SkipSelf() 23 | parentModule: CoreModule, 24 | ) { 25 | if (parentModule) { 26 | throw new Error('CoreModule is already loaded. Import only in AppModule'); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/app/core/error-handler/app-error-handler.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpErrorResponse } from '@angular/common/http'; 2 | import { ErrorHandler, Injectable } from '@angular/core'; 3 | import { NotificationService } from '@shared/services/notification.service'; 4 | 5 | import { environment } from '../../../environments/environment'; 6 | 7 | /** Application-wide error handler that adds a UI notification to the error handling 8 | * provided by the default Angular ErrorHandler. 9 | */ 10 | @Injectable() 11 | export class AppErrorHandler extends ErrorHandler { 12 | constructor(private notificationsService: NotificationService) { 13 | super(); 14 | } 15 | 16 | override handleError(error: Error | HttpErrorResponse) { 17 | let displayMessage = 'An error occurred.'; 18 | 19 | if (!environment.production) { 20 | displayMessage += ' See console for details.'; 21 | } 22 | 23 | this.notificationsService.error(displayMessage); 24 | 25 | super.handleError(error); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/core/http-interceptors/http-error.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; 2 | import { ErrorHandler, Injectable, Injector } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | import { tap } from 'rxjs/operators'; 5 | 6 | /** Passes HttpErrorResponse to application-wide error handler */ 7 | @Injectable() 8 | export class HttpErrorInterceptor implements HttpInterceptor { 9 | constructor(private injector: Injector) {} 10 | 11 | intercept(request: HttpRequest, next: HttpHandler): Observable> { 12 | return next.handle(request).pipe( 13 | tap({ 14 | error: (err: unknown) => { 15 | if (err instanceof HttpErrorResponse) { 16 | const appErrorHandler = this.injector.get(ErrorHandler); 17 | appErrorHandler.handleError(err); 18 | } 19 | }, 20 | }), 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/app/core/title/page-title.strategy.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Title } from '@angular/platform-browser'; 3 | import { RouterStateSnapshot, TitleStrategy } from '@angular/router'; 4 | 5 | import { environment as env } from '../../../environments/environment'; 6 | 7 | @Injectable() 8 | export class PageTitleStrategy extends TitleStrategy { 9 | constructor(private readonly title: Title) { 10 | super(); 11 | } 12 | 13 | override updateTitle(routerState: RouterStateSnapshot) { 14 | const title = this.buildTitle(routerState); 15 | if (title !== undefined) { 16 | this.title.setTitle(`${env.appName} - ${title}`); 17 | } else { 18 | this.title.setTitle(env.appName); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/core/utils/name-utils.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { NameUtils } from './name-utils.service'; 2 | 3 | describe('Test Name Utils', () => { 4 | it('contains spaces', () => { 5 | expect(NameUtils.sanitize(' no name ')).toEqual('noname'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /src/app/features/_features-theme.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | @mixin theme($theme) { 4 | mat-sidenav-container { 5 | } 6 | 7 | mat-list-item { 8 | &.active { 9 | background: rgba(mat.get-theme-color($theme, primary), 0.15); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/app/features/admin/settings/settings-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { SettingsComponent } from './settings.component'; 4 | import { UiComponent } from './ui/ui.component'; 5 | 6 | const routes: Routes = [ 7 | { path: '', redirectTo: 'ui', pathMatch: 'full' }, 8 | { 9 | path: '', 10 | component: SettingsComponent, 11 | children: [ 12 | { 13 | path: 'ui', 14 | component: UiComponent, 15 | }, 16 | ], 17 | }, 18 | ]; 19 | 20 | @NgModule({ 21 | imports: [RouterModule.forChild(routes)], 22 | exports: [RouterModule], 23 | }) 24 | export class SettingsRoutingModule {} 25 | -------------------------------------------------------------------------------- /src/app/features/admin/settings/settings.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Settings 4 | 5 | 6 | 7 |
8 | 17 | 18 | 19 |
20 | -------------------------------------------------------------------------------- /src/app/features/admin/settings/settings.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/admin/settings/settings.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { SettingsRoutingModule } from './settings-routing.module'; 4 | 5 | @NgModule({ 6 | declarations: [], 7 | imports: [SettingsRoutingModule], 8 | providers: [], 9 | }) 10 | export class SettingsModule {} 11 | -------------------------------------------------------------------------------- /src/app/features/admin/settings/ui/ui.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 350px; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/admin/spaces/space-dialog/space-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Space Form

2 | 3 |
4 |
5 | 6 | Name 7 | 8 | {{ form.controls['name'].value?.length || 0 }}/30 9 | @if (form.controls['name'].errors; as errors) { 10 | {{ fe.errors(errors) }} 11 | } 12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/app/features/admin/spaces/space-dialog/space-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/admin/spaces/space-dialog/space-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface SpaceDialogModel { 2 | name: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/admin/spaces/spaces-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { SpacesComponent } from './spaces.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: SpacesComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class SpacesRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/admin/spaces/spaces.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-header-cell, 6 | mat-cell { 7 | &.mat-column-id { 8 | max-width: 250px; 9 | } 10 | 11 | &.mat-column-createdAt { 12 | max-width: 120px; 13 | } 14 | 15 | &.mat-column-updatedAt { 16 | max-width: 120px; 17 | } 18 | 19 | &.mat-column-actions { 20 | max-width: 140px; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/features/admin/spaces/spaces.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SpacesRoutingModule } from './spaces-routing.module'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [SpacesRoutingModule], 7 | providers: [], 8 | }) 9 | export class SpacesModule {} 10 | -------------------------------------------------------------------------------- /src/app/features/admin/users/user-dialog/user-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/admin/users/user-dialog/user-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { UserPermission, UserRole } from '@shared/models/user.model'; 2 | 3 | export interface UserDialogModel { 4 | role?: UserRole; 5 | permissions?: UserPermission[]; 6 | lock?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/features/admin/users/user-invite-dialog/user-invite-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/admin/users/user-invite-dialog/user-invite-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { UserPermission, UserRole } from '@shared/models/user.model'; 2 | 3 | export interface UserInviteDialogResponse { 4 | displayName?: string; 5 | email: string; 6 | password: string; 7 | role?: UserRole; 8 | permissions?: UserPermission[]; 9 | lock?: boolean; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/features/admin/users/users-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { UsersComponent } from './users.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: UsersComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class UsersRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/admin/users/users.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-form-field { 6 | width: 100%; 7 | input { 8 | width: 100%; 9 | } 10 | } 11 | 12 | mat-header-cell, 13 | mat-cell { 14 | 15 | &.mat-column-active { 16 | max-width: 75px; 17 | } 18 | 19 | &.mat-column-providers { 20 | max-width: 95px; 21 | } 22 | 23 | &.mat-column-role { 24 | max-width: 150px; 25 | } 26 | 27 | &.mat-column-createdAt { 28 | max-width: 120px; 29 | } 30 | 31 | &.mat-column-updatedAt { 32 | max-width: 120px; 33 | } 34 | 35 | &.mat-column-actions { 36 | max-width: 125px; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/app/features/admin/users/users.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { UsersRoutingModule } from './users-routing.module'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [UsersRoutingModule], 7 | providers: [], 8 | }) 9 | export class UsersModule {} 10 | -------------------------------------------------------------------------------- /src/app/features/features.component.scss: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | height: calc(100% - 64px); 3 | } 4 | 5 | mat-sidenav-container { 6 | height: 100%; 7 | // when side-nav is collapsed 8 | mat-sidenav { 9 | width: 200px; 10 | border-right: 1px solid var(--mat-sys-outline-variant); 11 | border-radius: 0; 12 | &.collapsed { 13 | width: 56px; 14 | mat-list-item { 15 | padding-right: 0; 16 | mat-icon { 17 | margin-right: 16px; 18 | } 19 | } 20 | } 21 | } 22 | mat-sidenav-content { 23 | } 24 | } 25 | 26 | .vertical-divider { 27 | border-right: 1px solid var(--mat-sys-outline); 28 | @apply mx-1; 29 | } 30 | 31 | mat-form-field { 32 | width: 100%; 33 | } 34 | 35 | mat-icon.flash { 36 | color: var(--mat-sys-primary) 37 | } 38 | -------------------------------------------------------------------------------- /src/app/features/features.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SpaceService } from '@shared/services/space.service'; 3 | 4 | import { FeaturesRoutingModule } from './features-routing.module'; 5 | 6 | @NgModule({ 7 | declarations: [], 8 | imports: [FeaturesRoutingModule], 9 | providers: [SpaceService], 10 | schemas: [], 11 | }) 12 | export class FeaturesModule {} 13 | -------------------------------------------------------------------------------- /src/app/features/me/me-dialog/me-dialog.component.html: -------------------------------------------------------------------------------- 1 |

User

2 | 3 |
4 |
5 | 6 | Display Name 7 | 8 | 9 | 10 | Avatar 11 | 12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/app/features/me/me-dialog/me-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/me/me-dialog/me-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface MeDialogModel { 2 | displayName?: string; 3 | photoURL?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/features/me/me-email-dialog/me-email-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Update Email

2 | 3 |
4 |
5 | 6 | New Password 7 | 8 | Minimum 6 character 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/app/features/me/me-email-dialog/me-email-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/me/me-email-dialog/me-email-dialog.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; 3 | import { MatButtonModule } from '@angular/material/button'; 4 | import { MatDialogModule } from '@angular/material/dialog'; 5 | import { MatFormFieldModule } from '@angular/material/form-field'; 6 | import { MatInputModule } from '@angular/material/input'; 7 | 8 | @Component({ 9 | selector: 'll-me-email-dialog', 10 | templateUrl: './me-email-dialog.component.html', 11 | styleUrls: ['./me-email-dialog.component.scss'], 12 | changeDetection: ChangeDetectionStrategy.OnPush, 13 | imports: [MatDialogModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule], 14 | }) 15 | export class MeEmailDialogComponent { 16 | form: FormGroup = this.fb.group({ 17 | newEmail: this.fb.control('', [Validators.required, Validators.minLength(3)]), 18 | }); 19 | 20 | constructor(private readonly fb: FormBuilder) {} 21 | } 22 | -------------------------------------------------------------------------------- /src/app/features/me/me-email-dialog/me-email-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface MeEmailDialogModel { 2 | newEmail: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/me/me-password-dialog/me-password-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Update Password

2 | 3 |
4 |
5 | 6 | New Password 7 | 8 | Minimum 6 character 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/app/features/me/me-password-dialog/me-password-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/me/me-password-dialog/me-password-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface MePasswordDialogModel { 2 | newPassword: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/me/me-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { MeComponent } from './me.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: MeComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class MeRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/me/me.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/me/me.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { MeRoutingModule } from './me-routing.module'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [MeRoutingModule], 7 | providers: [], 8 | }) 9 | export class MeModule {} 10 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/add-folder-dialog/add-folder-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Create new Folder

2 | 3 |
4 |
5 | 6 | Name 7 | 8 | {{ form.controls['name'].value?.length || 0 }}/100 9 | @if (form.controls['name'].errors; as errors) { 10 | {{ fe.errors(errors) }} 11 | } 12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/add-folder-dialog/add-folder-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/add-folder-dialog/add-folder-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface AddFolderDialogModel { 2 | reservedNames: string[]; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/assets-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { AssetsComponent } from './assets.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: AssetsComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class AssetsRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/assets.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { AssetsRoutingModule } from './assets-routing.module'; 4 | 5 | @NgModule({ 6 | declarations: [], 7 | imports: [AssetsRoutingModule], 8 | providers: [], 9 | }) 10 | export class AssetsModule {} 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Edit File

2 | 3 |
4 |
5 | 6 | Name 7 | 8 | {{ data.asset.extension }} 9 | {{ form.controls['name'].value?.length || 0 }}/100 10 | @if (form.controls['name'].errors; as errors) { 11 | {{ fe.errors(errors) }} 12 | } 13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/edit-file-dialog/edit-file-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { AssetFile } from '@shared/models/asset.model'; 2 | 3 | export interface EditFileDialogModel { 4 | asset: AssetFile; 5 | reservedNames: string[]; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Edit Folder

2 | 3 |
4 |
5 | 6 | Name 7 | 8 | {{ form.controls['name'].value?.length || 0 }}/100 9 | @if (form.controls['name'].errors; as errors) { 10 | {{ fe.errors(errors) }} 11 | } 12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/edit-folder-dialog/edit-folder-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { AssetFolder } from '@shared/models/asset.model'; 2 | 3 | export interface EditFolderDialogModel { 4 | asset: AssetFolder; 5 | reservedNames: string[]; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/export-dialog/export-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/export-dialog/export-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ExportDialogModel { 2 | spaceId: string; 3 | } 4 | 5 | export interface ExportDialogReturn { 6 | /** 7 | * asset id 8 | */ 9 | path?: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/import-dialog/import-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Assets Import

2 | 3 |
4 |
5 | 9 |
10 | {{ fileName }} 11 |
12 | @if (fileWrong) { 13 | The selected file does not comply with import extension (*.lla.zip). 14 | } 15 |
16 |
17 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/import-dialog/import-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/import-dialog/import-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ImportDialogReturn { 2 | file: File; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/move-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './move-dialog.component'; 2 | export * from './move-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/move-dialog/move-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/assets/move-dialog/move-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface MoveDialogModel { 2 | spaceId: string; 3 | } 4 | 5 | export interface MoveDialogReturn { 6 | /** 7 | * Asset parent path 8 | */ 9 | path: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/add-document-dialog/add-document-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/add-document-dialog/add-document-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from '@shared/models/schema.model'; 2 | 3 | export interface AddDocumentDialogModel { 4 | schemas: Schema[]; 5 | reservedNames: string[]; 6 | reservedSlugs: string[]; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/add-document-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './add-document-dialog.component'; 2 | export * from './add-document-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/add-folder-dialog/add-folder-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/add-folder-dialog/add-folder-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface AddFolderDialogModel { 2 | reservedNames: string[]; 3 | reservedSlugs: string[]; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/add-folder-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './add-folder-dialog.component'; 2 | export * from './add-folder-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/contents-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { isFormDirtyGuard } from '@shared/guards/dirty-form.guard'; 4 | import { ContentsComponent } from './contents.component'; 5 | import { EditDocumentComponent } from './edit-document/edit-document.component'; 6 | 7 | const routes: Routes = [ 8 | { 9 | path: '', 10 | component: ContentsComponent, 11 | }, 12 | { 13 | path: ':contentId', 14 | component: EditDocumentComponent, 15 | canDeactivate: [isFormDirtyGuard], 16 | }, 17 | ]; 18 | 19 | @NgModule({ 20 | imports: [RouterModule.forChild(routes)], 21 | exports: [RouterModule], 22 | }) 23 | export class ContentsRoutingModule {} 24 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/contents.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-row { 6 | cursor: pointer; 7 | } 8 | 9 | mat-cell { 10 | &.mat-column-preview { 11 | max-width: 150px; 12 | 13 | img { 14 | max-width: 115px; 15 | max-height: 115px; 16 | } 17 | } 18 | } 19 | 20 | mat-header-cell, 21 | mat-cell { 22 | &.mat-column-select { 23 | max-width: 80px; 24 | } 25 | 26 | &.mat-column-status { 27 | max-width: 80px; 28 | } 29 | 30 | &.mat-column-publishedAt { 31 | max-width: 220px; 32 | } 33 | 34 | &.mat-column-createdAt { 35 | max-width: 120px; 36 | } 37 | 38 | &.mat-column-updatedAt { 39 | max-width: 120px; 40 | } 41 | 42 | &.mat-column-actions { 43 | max-width: 250px; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/contents.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { MarkdownModule } from 'ngx-markdown'; 3 | import { ContentsRoutingModule } from './contents-routing.module'; 4 | 5 | @NgModule({ 6 | declarations: [], 7 | imports: [ContentsRoutingModule, MarkdownModule.forChild()], 8 | providers: [], 9 | }) 10 | export class ContentsModule {} 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/edit-dialog/edit-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/edit-dialog/edit-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { Content } from '@shared/models/content.model'; 2 | 3 | export interface EditDialogModel { 4 | content: Content; 5 | reservedNames: string[]; 6 | reservedSlugs: string[]; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/edit-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './edit-dialog.component'; 2 | export * from './edit-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/edit-document-schema/edit-document-schema.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | 5 | .schema-id { 6 | color: var(--mat-sys-secondary); 7 | } 8 | .error { 9 | color: var(--mat-sys-error); 10 | } 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/edit-document-schema/edit-document-schema.model.ts: -------------------------------------------------------------------------------- 1 | export interface SchemaSelectChange { 2 | contentId: string; 3 | fieldName: string; 4 | schemaName: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/edit-document/edit-document.model.ts: -------------------------------------------------------------------------------- 1 | export interface SchemaPathItem { 2 | contentId: string; 3 | fieldName: string; 4 | schemaName: string; 5 | } 6 | 7 | // Events 8 | 9 | // Event emitted from Application to Visual Editor 10 | export type EventToEditorType = 'selectSchema' | 'hoverSchema' | 'leaveSchema'; 11 | export type EventToEditor = { owner: 'LOCALESS'; type: EventToEditorType; id: string; schema: string; field?: string }; 12 | 13 | // Event emitted from Visual Editor to Application 14 | export type EventToAppType = 'save' | 'publish' | 'input' | 'change' | 'enterSchema' | 'hoverSchema'; 15 | export type EventToApp = 16 | | { type: 'save' | 'publish' } 17 | | { type: 'input' | 'change'; data: any } 18 | | { type: 'enterSchema' | 'hoverSchema'; id: string; schema: string; field?: string }; 19 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/export-dialog/export-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/export-dialog/export-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ExportDialogModel { 2 | spaceId: string; 3 | } 4 | 5 | export interface ExportDialogReturn { 6 | /** 7 | * content id 8 | */ 9 | path?: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/export-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './export-dialog.component'; 2 | export * from './export-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/import-dialog/import-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Contents Import

2 | 3 |
4 |
5 | 9 |
10 | {{ fileName }} 11 |
12 | @if (fileWrong) { 13 | The selected file does not comply with import extension (*.llc.zip). 14 | } 15 |
16 |
17 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/import-dialog/import-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/import-dialog/import-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ImportDialogReturn { 2 | file: File; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/import-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './import-dialog.component'; 2 | export * from './import-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/move-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './move-dialog.component'; 2 | export * from './move-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/move-dialog/move-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/move-dialog/move-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface MoveDialogModel { 2 | spaceId: string; 3 | } 4 | 5 | export interface MoveDialogReturn { 6 | /** 7 | * content full slug 8 | */ 9 | path: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/shared/asset-select/asset-select.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | 5 | mat-grid-tile { 6 | //background: $grey-color; 7 | } 8 | 9 | //img:hover { 10 | // position: relative; 11 | // overflow: hidden; 12 | // transform: scale(1.5); /* Adjust the scale as needed */ 13 | // transition: transform 0.3s ease-in-out; 14 | //} 15 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/shared/assets-select/assets-select.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | 5 | mat-grid-tile { 6 | //background: $grey-color; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/shared/link-select/link-select.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/shared/reference-select/reference-select.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 99%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/shared/references-select/references-select.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/contents/shared/rich-text-editor/rich-text-editor.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | 5 | .vertical-divider { 6 | border-right: 1px solid var(--mat-sys-outline); 7 | @apply mx-1; 8 | } 9 | 10 | button.selected { 11 | color: var(--mat-standard-button-toggle-selected-state-text-color, var(--mat-sys-on-secondary-container)); 12 | background-color: var(--mat-standard-button-toggle-selected-state-background-color, var(--mat-sys-secondary-container)); 13 | } 14 | -------------------------------------------------------------------------------- /src/app/features/spaces/dashboard/dashboard-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { DashboardComponent } from './dashboard.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: DashboardComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class DashboardRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/spaces/dashboard/dashboard.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/app/features/spaces/dashboard/dashboard.component.scss -------------------------------------------------------------------------------- /src/app/features/spaces/dashboard/dashboard.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { DashboardRoutingModule } from './dashboard-routing.module'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [DashboardRoutingModule], 7 | providers: [], 8 | }) 9 | export class DashboardModule {} 10 | -------------------------------------------------------------------------------- /src/app/features/spaces/open-api/open-api-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { OpenApiComponent } from './open-api.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: OpenApiComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class OpenApiRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/spaces/open-api/open-api.component.html: -------------------------------------------------------------------------------- 1 | @if (openApiDocument$ | async; as openApiDocument) { 2 | 3 | } @else { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/app/features/spaces/open-api/open-api.component.scss: -------------------------------------------------------------------------------- 1 | @import "@stoplight/elements/styles.min.css"; 2 | -------------------------------------------------------------------------------- /src/app/features/spaces/open-api/open-api.module.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; 2 | import { OpenApiRoutingModule } from './open-api-routing.module'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [OpenApiRoutingModule], 7 | providers: [], 8 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 9 | }) 10 | export class OpenApiModule {} 11 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/add-dialog/add-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/add-dialog/add-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface AddDialogModel { 2 | reservedIds: string[]; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/edit-comp/edit-comp.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | 5 | .badge { 6 | @apply inline-flex items-center rounded-md bg-indigo-50 px-2 py-1 mx-1 text-xs font-medium text-indigo-700 ring-1 ring-inset ring-indigo-700/10 7 | } 8 | 9 | .title { 10 | font: var(--mat-sys-title-large); 11 | } 12 | 13 | .subtitle { 14 | font: var(--mat-sys-title-medium); 15 | color: var(--mat-sys-secondary); 16 | } 17 | 18 | .field-id { 19 | color: var(--mat-sys-secondary); 20 | } 21 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/edit-enum/edit-enum.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | 5 | .title { 6 | font: var(--mat-sys-title-large); 7 | } 8 | 9 | .subtitle { 10 | font: var(--mat-sys-title-medium); 11 | color: var(--mat-sys-secondary); 12 | } 13 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/edit-id-dialog/edit-id-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/edit-id-dialog/edit-id-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface EditIdDialogModel { 2 | id: string; 3 | reservedIds: string[]; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/edit-id-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './edit-id-dialog.component'; 2 | export * from './edit-id-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/export-dialog/export-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Schema Export

2 | 3 |
4 |
5 | 6 | From Date 7 | 8 | 9 | clear 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/export-dialog/export-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/export-dialog/export-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ExportDialogReturn { 2 | /** 3 | * number of milliseconds. 4 | */ 5 | fromDate?: number; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/import-dialog/import-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Schema Import

2 | 3 |
4 |
5 | 9 |
10 | {{ fileName }} 11 |
12 | @if (fileWrong) { 13 | The selected file does not comply with import extension (*.lls.zip). 14 | } 15 |
16 |
17 | 18 | 19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/import-dialog/import-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/import-dialog/import-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ImportDialogReturn { 2 | file: File; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/schemas-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { isFormDirtyGuard } from '@shared/guards/dirty-form.guard'; 4 | import { EditCompComponent } from './edit-comp/edit-comp.component'; 5 | import { EditEnumComponent } from './edit-enum/edit-enum.component'; 6 | import { SchemasComponent } from './schemas.component'; 7 | 8 | const routes: Routes = [ 9 | { 10 | path: '', 11 | component: SchemasComponent, 12 | }, 13 | { 14 | path: 'comp/:schemaId', 15 | component: EditCompComponent, 16 | canDeactivate: [isFormDirtyGuard], 17 | }, 18 | { 19 | path: 'enum/:schemaId', 20 | component: EditEnumComponent, 21 | canDeactivate: [isFormDirtyGuard], 22 | }, 23 | ]; 24 | 25 | @NgModule({ 26 | imports: [RouterModule.forChild(routes)], 27 | exports: [RouterModule], 28 | }) 29 | export class SchemasRoutingModule {} 30 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/schemas.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-form-field { 6 | width: 100%; 7 | input { 8 | width: 100%; 9 | } 10 | } 11 | 12 | .schema-id { 13 | color: var(--mat-sys-secondary); 14 | } 15 | 16 | mat-row { 17 | cursor: pointer; 18 | } 19 | 20 | mat-header-cell, 21 | mat-cell { 22 | &.mat-column-type { 23 | max-width: 120px; 24 | } 25 | 26 | &.mat-column-createdAt { 27 | max-width: 120px; 28 | } 29 | 30 | &.mat-column-updatedAt { 31 | max-width: 120px; 32 | } 33 | 34 | &.mat-column-actions { 35 | max-width: 125px; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/schemas.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { SchemasRoutingModule } from './schemas-routing.module'; 4 | 5 | @NgModule({ 6 | declarations: [], 7 | imports: [SchemasRoutingModule], 8 | providers: [], 9 | exports: [], 10 | }) 11 | export class SchemasModule {} 12 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/shared/edit-field/edit-field.component.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | @import '../../../../../../styles/styles-variables'; 4 | 5 | mat-form-field { 6 | width: 100%; 7 | } 8 | 9 | .mat-expansion-panel-header-title { 10 | justify-content: space-between; 11 | align-items: center; 12 | } 13 | mat-expansion-panel { 14 | mat-icon.cdk-drag-handle { 15 | cursor: grab; 16 | } 17 | &.invalid { 18 | border: solid 2px var(--mat-sys-error); 19 | } 20 | } 21 | 22 | .cdk-drag-preview { 23 | box-sizing: border-box; 24 | border-radius: 4px; 25 | box-shadow: 26 | 0 5px 5px -3px rgba(0, 0, 0, 0.2), 27 | 0 8px 10px 1px rgba(0, 0, 0, 0.14), 28 | 0 3px 14px 2px rgba(0, 0, 0, 0.12); 29 | } 30 | 31 | .cdk-drag-placeholder { 32 | opacity: 0; 33 | } 34 | 35 | .cdk-drag-animating { 36 | transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); 37 | } 38 | -------------------------------------------------------------------------------- /src/app/features/spaces/schemas/shared/edit-value/edit-value.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/general/general.component.scss: -------------------------------------------------------------------------------- 1 | //@use 'sass:map'; 2 | //@use '@angular/material' as mat; 3 | 4 | //@import '../../../../styles'; 5 | // 6 | //$color-config: mat.get-color-config($theme); 7 | //$primary-palette: map.get($color-config, 'primary'); 8 | //$primary-color: mat.get-color-from-palette($primary-palette); 9 | 10 | mat-form-field { 11 | width: 350px; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/locales/locale-dialog/locale-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Locale Form

2 | 3 |
4 |
5 | 6 | Locale 7 | 8 | 9 | @for (locale of filteredLocales | async; track locale.id) { 10 | {{ locale.name }} ({{ locale.id }}) 11 | } 12 | 13 | @if (form.controls['locale'].errors; as errors) { 14 | {{ fe.errors(errors) }} 15 | } 16 | 17 |
18 |
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/locales/locale-dialog/locale-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/locales/locale-dialog/locale-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { Locale } from '@shared/models/locale.model'; 2 | 3 | export interface LocaleDialogModel { 4 | locale: Locale; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/locales/locales.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-cell.mat-column-actions { 6 | max-width: 100px; 7 | } 8 | 9 | mat-header-cell.mat-column-actions { 10 | max-width: 100px; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/settings.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Settings 4 | 5 | 6 | 7 |
8 | 17 | 18 | 19 |
20 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/settings.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/settings.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SettingsRoutingModule } from './settings-routing.module'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [SettingsRoutingModule], 7 | providers: [], 8 | }) 9 | export class SettingsModule {} 10 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/tokens/token-dialog/token-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Token Form

2 | 3 |
4 |
5 | 6 | Name 7 | 8 | {{ form.controls['name'].value?.length || 0 }}/30 9 | @if (form.controls['name'].errors; as errors) { 10 | {{ fe.errors(errors) }} 11 | } 12 | 13 |
14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/tokens/token-dialog/token-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/tokens/token-dialog/token-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface TokenDialogModel { 2 | name: string; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/tokens/tokens.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-header-cell, 6 | mat-cell { 7 | &.mat-column-id { 8 | max-width: 250px; 9 | } 10 | &.mat-column-actions { 11 | max-width: 100px; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/app/features/spaces/settings/visual-editor/visual-editor.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 350px; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/tasks/tasks-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { TasksComponent } from './tasks.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: TasksComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class TasksRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/spaces/tasks/tasks.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-header-cell, 6 | mat-cell { 7 | &.mat-column-id { 8 | max-width: 220px; 9 | } 10 | 11 | &.mat-column-kind { 12 | max-width: 160px; 13 | } 14 | 15 | &.mat-column-status { 16 | max-width: 80px; 17 | } 18 | 19 | &.mat-column-description { 20 | max-width: 300px; 21 | } 22 | 23 | &.mat-column-createdAt { 24 | max-width: 120px; 25 | } 26 | 27 | &.mat-column-updatedAt { 28 | max-width: 120px; 29 | } 30 | 31 | &.mat-column-actions { 32 | max-width: 125px; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/features/spaces/tasks/tasks.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { TasksRoutingModule } from './tasks-routing.module'; 3 | 4 | @NgModule({ 5 | declarations: [], 6 | imports: [TasksRoutingModule], 7 | providers: [], 8 | }) 9 | export class TasksModule {} 10 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/add-dialog/add-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/add-dialog/add-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { TranslationType } from '@shared/models/translation.model'; 2 | 3 | export interface AddDialogModel { 4 | reservedIds: string[]; 5 | } 6 | 7 | export interface AddDialogReturnModel { 8 | id: string; 9 | type: TranslationType; 10 | value: string; 11 | labels: string[]; 12 | description: string; 13 | autoTranslate?: boolean; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/add-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './add-dialog.component'; 2 | export * from './add-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/edit-dialog/edit-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/edit-dialog/edit-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface EditDialogModel { 2 | labels: string[]; 3 | description: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/edit-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './edit-dialog.component'; 2 | export * from './edit-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/edit-id-dialog/edit-id-dialog.component.html: -------------------------------------------------------------------------------- 1 |

Edit Translation ID

2 | 3 |
4 |
5 | 6 | Id 7 | 8 | Will be used in OpenAPI Schema Name. 9 | {{ form.controls['id'].value?.length || 0 }}/150 10 | @if (form.controls['id'].errors; as errors) { 11 | {{ fe.errors(errors) }} 12 | } 13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/edit-id-dialog/edit-id-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/edit-id-dialog/edit-id-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface EditIdDialogModel { 2 | id: string; 3 | reservedIds: string[]; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/edit-id-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './edit-id-dialog.component'; 2 | export * from './edit-id-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/export-dialog/export-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/export-dialog/export-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { Locale } from '@shared/models/locale.model'; 2 | 3 | export interface ExportDialogModel { 4 | locales: Locale[]; 5 | } 6 | 7 | export type ExportDialogReturn = ExportFullDialogReturn | ExportFlatDialogReturn; 8 | 9 | export interface ExportFullDialogReturn { 10 | kind: 'FULL'; 11 | /** 12 | * number of milliseconds. 13 | */ 14 | fromDate?: number; 15 | } 16 | 17 | export interface ExportFlatDialogReturn { 18 | kind: 'FLAT'; 19 | locale: string; 20 | /** 21 | * number of milliseconds. 22 | */ 23 | fromDate?: number; 24 | } 25 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/import-dialog/import-dialog.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/import-dialog/import-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { Locale } from '@shared/models/locale.model'; 2 | 3 | export interface ImportDialogModel { 4 | locales: Locale[]; 5 | } 6 | 7 | export type ImportDialogReturn = ImportFullDialogReturn | ImportFlatDialogReturn; 8 | 9 | export interface ImportFullDialogReturn { 10 | kind: 'FULL'; 11 | file: File; 12 | } 13 | 14 | export interface ImportFlatDialogReturn { 15 | kind: 'FLAT'; 16 | locale: string; 17 | file: File; 18 | } 19 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/shared/models/translation.model.ts: -------------------------------------------------------------------------------- 1 | export interface TranslationNode { 2 | name: string; 3 | key: string; 4 | children?: TranslationNode[]; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-array-edit/translation-array-edit.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | 8 | .edit-array { 9 | overflow-y: auto; 10 | max-height: 500px; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-array-view/translation-array-view.component.html: -------------------------------------------------------------------------------- 1 |
    2 | @for (item of extract(); track item) { 3 |
  • {{ item }}
  • 4 | } 5 |
6 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-array-view/translation-array-view.component.scss: -------------------------------------------------------------------------------- 1 | ul { 2 | padding-left: 0; 3 | list-style: none; 4 | margin-bottom: 0; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-array-view/translation-array-view.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'll-translation-array-view', 5 | standalone: true, 6 | templateUrl: './translation-array-view.component.html', 7 | styleUrls: ['./translation-array-view.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | }) 10 | export class TranslationArrayViewComponent { 11 | value = input.required(); 12 | 13 | extract(): string[] { 14 | return JSON.parse(this.value() || '[]'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-plural-edit/translation-plural-edit.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-plural-view/translation-plural-view.component.html: -------------------------------------------------------------------------------- 1 |
    2 | @for (item of extract() | keyvalue; track item.key) { 3 |
  • 4 | {{ toPlural(item.key) }} : {{ item.value }} 5 |
  • 6 | } 7 |
8 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-plural-view/translation-plural-view.component.scss: -------------------------------------------------------------------------------- 1 | ul { 2 | padding-left: 0; 3 | list-style: none; 4 | margin-bottom: 0; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-string-edit/translation-string-edit.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | {{ input.value?.length || 0 }}/1000 5 | 6 |
7 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-string-edit/translation-string-edit.component.scss: -------------------------------------------------------------------------------- 1 | mat-form-field { 2 | width: 100%; 3 | input { 4 | width: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-string-view/translation-string-view.component.html: -------------------------------------------------------------------------------- 1 | {{ value() }} 2 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-string-view/translation-string-view.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/app/features/spaces/translations/translation-string-view/translation-string-view.component.scss -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translation-string-view/translation-string-view.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'll-translation-string-view', 5 | standalone: true, 6 | templateUrl: './translation-string-view.component.html', 7 | styleUrls: ['./translation-string-view.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | }) 10 | export class TranslationStringViewComponent { 11 | value = input.required(); 12 | } 13 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translations-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { TranslationsComponent } from './translations.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | component: TranslationsComponent, 9 | }, 10 | ]; 11 | 12 | @NgModule({ 13 | imports: [RouterModule.forChild(routes)], 14 | exports: [RouterModule], 15 | }) 16 | export class TranslationsRoutingModule {} 17 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translations.component.scss: -------------------------------------------------------------------------------- 1 | .search-buttons { 2 | width: 10em; 3 | } 4 | 5 | .disabled { 6 | pointer-events: none; 7 | opacity: 0.5; 8 | } 9 | 10 | .selected { 11 | //--mat-standard-button-toggle-selected-state-background-color #dae2f9 12 | background-color: var(--mat-sys-secondary-container); 13 | } 14 | 15 | mat-sidenav { 16 | width: 30%; 17 | } 18 | 19 | mat-form-field { 20 | width: 100%; 21 | 22 | input { 23 | width: 100%; 24 | } 25 | } 26 | 27 | mat-form-field.with-button { 28 | width: calc(100% - 50px); 29 | 30 | input { 31 | width: 100%; 32 | } 33 | } 34 | 35 | .overlay { 36 | height: calc(100vh - 216px); 37 | padding: inherit; 38 | border: 1px solid #efefef; 39 | } 40 | 41 | :host ::ng-deep .cdk-virtual-scroll-content-wrapper { 42 | max-width: 100%; 43 | } 44 | -------------------------------------------------------------------------------- /src/app/features/spaces/translations/translations.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { TranslationsRoutingModule } from './translations-routing.module'; 4 | 5 | @NgModule({ 6 | declarations: [], 7 | imports: [TranslationsRoutingModule], 8 | providers: [], 9 | }) 10 | export class TranslationsModule {} 11 | -------------------------------------------------------------------------------- /src/app/features/welcome/welcome.component.scss: -------------------------------------------------------------------------------- 1 | h2 { 2 | @apply text-center; 3 | font: var(--mat-sys-headline-small); 4 | } 5 | 6 | h3 { 7 | font: var(--mat-sys-title-small); 8 | } 9 | 10 | a { 11 | color: var(--mat-sys-primary); 12 | text-decoration: underline; 13 | } 14 | -------------------------------------------------------------------------------- /src/app/features/welcome/welcome.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'll-welcome', 5 | templateUrl: './welcome.component.html', 6 | styleUrl: './welcome.component.scss', 7 | changeDetection: ChangeDetectionStrategy.OnPush, 8 | imports: [], 9 | }) 10 | export class WelcomeComponent { 11 | constructor() {} 12 | } 13 | -------------------------------------------------------------------------------- /src/app/login/login.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | color: var(--mat-app-text-color); 3 | } 4 | mat-form-field { 5 | width: 100%; 6 | input { 7 | width: 100%; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/reset/reset.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | color: var(--mat-app-text-color); 3 | } 4 | mat-form-field { 5 | width: 100%; 6 | input { 7 | width: 100%; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/setup/setup.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | color: var(--mat-app-text-color); 3 | } 4 | mat-form-field { 5 | width: 100%; 6 | input { 7 | width: 100%; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/setup/setup.model.ts: -------------------------------------------------------------------------------- 1 | export interface Setup { 2 | admin: { 3 | displayName?: string; 4 | email: string; 5 | password: string; 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/setup/setup.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Functions, httpsCallableData } from '@angular/fire/functions'; 3 | import { traceUntilFirst } from '@angular/fire/performance'; 4 | import { Observable } from 'rxjs'; 5 | import { Setup } from './setup.model'; 6 | 7 | @Injectable() 8 | export class SetupService { 9 | constructor(private readonly functions: Functions) {} 10 | 11 | init(setup: Setup): Observable { 12 | const setupFunction = httpsCallableData(this.functions, 'setup'); 13 | return setupFunction(setup).pipe(traceUntilFirst('Firestore:setup')); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/components/assets-select-dialog/assets-select-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { AssetFileType } from '@shared/models/schema.model'; 2 | 3 | export interface AssetsSelectDialogModel { 4 | spaceId: string; 5 | multiple?: boolean; 6 | fileType?: AssetFileType; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/shared/components/breadcrumb/breadcrumb-item.component.scss: -------------------------------------------------------------------------------- 1 | span { 2 | cursor: pointer; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/shared/components/breadcrumb/breadcrumb-item.component.ts: -------------------------------------------------------------------------------- 1 | import { booleanAttribute, ChangeDetectionStrategy, Component, input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'll-breadcrumb-item', 5 | standalone: true, 6 | templateUrl: './breadcrumb-item.component.html', 7 | styleUrls: ['./breadcrumb-item.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | }) 10 | export class BreadcrumbItemComponent { 11 | home = input(false, { transform: booleanAttribute }); 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/components/breadcrumb/breadcrumb.component.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/app/shared/components/breadcrumb/breadcrumb.component.scss: -------------------------------------------------------------------------------- 1 | :host ::ng-deep ll-breadcrumb-item:last-child { 2 | pointer-events: none; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/shared/components/breadcrumb/breadcrumb.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'll-breadcrumb', 5 | standalone: true, 6 | templateUrl: './breadcrumb.component.html', 7 | styleUrls: ['./breadcrumb.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | }) 10 | export class BreadcrumbComponent {} 11 | -------------------------------------------------------------------------------- /src/app/shared/components/breadcrumb/index.ts: -------------------------------------------------------------------------------- 1 | export * from './breadcrumb.component'; 2 | export * from './breadcrumb-item.component'; 3 | -------------------------------------------------------------------------------- /src/app/shared/components/confirmation-dialog/confirmation-dialog.component.html: -------------------------------------------------------------------------------- 1 |

{{ data.title }}

2 | 3 |

4 | {{ data.content }} 5 |

6 |
7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/app/shared/components/confirmation-dialog/confirmation-dialog.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/app/shared/components/confirmation-dialog/confirmation-dialog.component.scss -------------------------------------------------------------------------------- /src/app/shared/components/confirmation-dialog/confirmation-dialog.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; 2 | import { MatButtonModule } from '@angular/material/button'; 3 | import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; 4 | import { ConfirmationDialogModel } from './confirmation-dialog.model'; 5 | 6 | @Component({ 7 | selector: 'll-confirmation-dialog', 8 | templateUrl: './confirmation-dialog.component.html', 9 | styleUrls: ['./confirmation-dialog.component.scss'], 10 | changeDetection: ChangeDetectionStrategy.OnPush, 11 | imports: [MatDialogModule, MatButtonModule], 12 | }) 13 | export class ConfirmationDialogComponent { 14 | constructor(@Inject(MAT_DIALOG_DATA) public data: ConfirmationDialogModel) {} 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/components/confirmation-dialog/confirmation-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ConfirmationDialogModel { 2 | title: string; 3 | content: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/shared/components/confirmation-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './confirmation-dialog.component'; 2 | export * from './confirmation-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/shared/components/custom-snack-bar/custom-snack-bar.component.html: -------------------------------------------------------------------------------- 1 |
{{ data.message }}
2 | 3 | @if (data.actions) { 4 |
5 | @for (action of data.actions; track action.label) { 6 | 9 | } 10 |
11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/components/custom-snack-bar/custom-snack-bar.model.ts: -------------------------------------------------------------------------------- 1 | export interface CustomSnackBarModel { 2 | message: string; 3 | actions?: ActionRoute[]; 4 | } 5 | 6 | export interface ActionRoute { 7 | label: string; 8 | link: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/components/image-preview-dialog/image-preview-dialog.component.scss: -------------------------------------------------------------------------------- 1 | .vertical-divider { 2 | border-right: 1px solid var(--mat-sys-outline); 3 | @apply mx-1; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/shared/components/image-preview-dialog/image-preview-dialog.model.ts: -------------------------------------------------------------------------------- 1 | import { AssetFile } from '@shared/models/asset.model'; 2 | 3 | export interface ImagePreviewDialogModel { 4 | spaceId: string; 5 | asset: AssetFile; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/shared/components/references-select-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './references-select-dialog.component'; 2 | export * from './references-select-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/shared/components/references-select-dialog/references-select-dialog.component.scss: -------------------------------------------------------------------------------- 1 | table { 2 | width: 100%; 3 | } 4 | 5 | mat-dialog-content { 6 | @apply pt-0 #{!important}; 7 | @apply pb-1 #{!important}; 8 | } 9 | 10 | mat-row { 11 | cursor: pointer; 12 | } 13 | 14 | mat-header-cell, 15 | mat-cell { 16 | &.mat-column-select { 17 | max-width: 80px; 18 | } 19 | &.mat-column-status { 20 | max-width: 80px; 21 | } 22 | &.mat-column-updatedAt { 23 | max-width: 130px; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shared/components/references-select-dialog/references-select-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface ReferencesSelectDialogModel { 2 | spaceId: string; 3 | multiple?: boolean; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/shared/components/status/index.ts: -------------------------------------------------------------------------------- 1 | export * from './status.component'; 2 | export * from './status.model'; 3 | -------------------------------------------------------------------------------- /src/app/shared/components/status/status.component.html: -------------------------------------------------------------------------------- 1 | @switch (mode()) { 2 | @case ('online') { 3 |
4 |
5 |
6 | } 7 | @case ('away') { 8 |
9 |
10 |
11 | } 12 | @case ('offline') { 13 |
14 |
15 |
16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/components/status/status.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | align-items: center; 4 | @apply p-1 5 | } 6 | -------------------------------------------------------------------------------- /src/app/shared/components/status/status.component.ts: -------------------------------------------------------------------------------- 1 | import { ChangeDetectionStrategy, Component, input } from '@angular/core'; 2 | import { StatusMode } from '@shared/components/status/status.model'; 3 | 4 | @Component({ 5 | selector: 'll-status', 6 | templateUrl: './status.component.html', 7 | styleUrls: ['./status.component.scss'], 8 | changeDetection: ChangeDetectionStrategy.OnPush, 9 | imports: [], 10 | }) 11 | export class StatusComponent { 12 | mode = input.required(); 13 | } 14 | -------------------------------------------------------------------------------- /src/app/shared/components/status/status.model.ts: -------------------------------------------------------------------------------- 1 | export type StatusMode = 'online' | 'offline' | 'away'; 2 | -------------------------------------------------------------------------------- /src/app/shared/components/unsplash-assets-select-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export * from './unsplash-assets-select-dialog.component'; 2 | export * from './unsplash-assets-select-dialog.model'; 3 | -------------------------------------------------------------------------------- /src/app/shared/components/unsplash-assets-select-dialog/unsplash-assets-select-dialog.component.scss: -------------------------------------------------------------------------------- 1 | .header-actions { 2 | @apply mt-1 float-right flex gap-4 items-center; 3 | } 4 | 5 | mat-dialog-content { 6 | @apply pt-0 #{!important}; 7 | @apply pb-1 #{!important}; 8 | } 9 | 10 | mat-form-field { 11 | width: 100%; 12 | input { 13 | width: 100%; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/components/unsplash-assets-select-dialog/unsplash-assets-select-dialog.model.ts: -------------------------------------------------------------------------------- 1 | export interface UnsplashAssetsSelectDialogModel { 2 | spaceId: string; 3 | multiple?: boolean; 4 | } 5 | 6 | export interface UnsplashAssetsSelectDialogModel { 7 | spaceId: string; 8 | multiple?: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/directives/animate.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, effect, ElementRef, input } from '@angular/core'; 2 | 3 | type AnimationClass = 'animate-spin' | 'animate-ping' | 'animate-pulse' | 'animate-bounce' | 'animate-none'; 4 | 5 | @Directive({ 6 | selector: '[llAnimate]', 7 | standalone: true, 8 | }) 9 | export class AnimateDirective { 10 | animate = input(false, { alias: 'llAnimate' }); 11 | class = input('animate-spin', { alias: 'llAnimateClass' }); 12 | 13 | constructor(private hostElement: ElementRef) { 14 | effect(() => { 15 | if (this.animate()) { 16 | this.hostElement.nativeElement.classList.add(this.class()); 17 | } else { 18 | this.hostElement.nativeElement.classList.remove(this.class()); 19 | } 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/api-configuration.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { Injectable } from '@angular/core'; 4 | 5 | /** 6 | * Global configuration 7 | */ 8 | @Injectable({ 9 | providedIn: 'root', 10 | }) 11 | export class ApiConfiguration { 12 | rootUrl: string = 'https://api.github.com'; 13 | } 14 | 15 | /** 16 | * Parameters for `ApiModule.forRoot()` 17 | */ 18 | export interface ApiConfigurationParams { 19 | rootUrl?: string; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/base-service.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { Injectable } from '@angular/core'; 4 | import { HttpClient } from '@angular/common/http'; 5 | import { ApiConfiguration } from './api-configuration'; 6 | 7 | /** 8 | * Base class for services 9 | */ 10 | @Injectable() 11 | export class BaseService { 12 | constructor( 13 | protected config: ApiConfiguration, 14 | protected http: HttpClient 15 | ) { 16 | } 17 | 18 | private _rootUrl?: string; 19 | 20 | /** 21 | * Returns the root url for all operations in this service. If not set directly in this 22 | * service, will fallback to `ApiConfiguration.rootUrl`. 23 | */ 24 | get rootUrl(): string { 25 | return this._rootUrl || this.config.rootUrl; 26 | } 27 | 28 | /** 29 | * Sets the root URL for API operations in this service. 30 | */ 31 | set rootUrl(rootUrl: string) { 32 | this._rootUrl = rootUrl; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/activity.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 4 | 5 | /** 6 | * Activity 7 | */ 8 | export interface Activity { 9 | 10 | /** 11 | * The type of the activity that was performed. 12 | */ 13 | activity_type: 'push' | 'force_push' | 'branch_deletion' | 'branch_creation' | 'pr_merge' | 'merge_queue_merge'; 14 | actor: NullableSimpleUser | null; 15 | 16 | /** 17 | * The SHA of the commit after the activity. 18 | */ 19 | after: string; 20 | 21 | /** 22 | * The SHA of the commit before the activity. 23 | */ 24 | before: string; 25 | id: number; 26 | node_id: string; 27 | 28 | /** 29 | * The full Git reference, formatted as `refs/heads/`. 30 | */ 31 | ref: string; 32 | 33 | /** 34 | * The time when the activity occurred. 35 | */ 36 | timestamp: string; 37 | } 38 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/author-association.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * How the author is associated with the repository. 6 | */ 7 | export enum AuthorAssociation { 8 | Collaborator = 'COLLABORATOR', 9 | Contributor = 'CONTRIBUTOR', 10 | FirstTimer = 'FIRST_TIMER', 11 | FirstTimeContributor = 'FIRST_TIME_CONTRIBUTOR', 12 | Mannequin = 'MANNEQUIN', 13 | Member = 'MEMBER', 14 | None = 'NONE', 15 | Owner = 'OWNER' 16 | } 17 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/auto-merge.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { SimpleUser } from '../models/simple-user'; 4 | 5 | /** 6 | * The status of auto merging a pull request. 7 | */ 8 | export type AutoMerge = ({ 9 | 'enabled_by': SimpleUser; 10 | 11 | /** 12 | * The merge method to use. 13 | */ 14 | 'merge_method': 'merge' | 'squash' | 'rebase'; 15 | 16 | /** 17 | * Title for the merge commit message. 18 | */ 19 | 'commit_title': string; 20 | 21 | /** 22 | * Commit message for the merge commit. 23 | */ 24 | 'commit_message': string; 25 | }) | null; 26 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/autolink.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * An autolink reference. 6 | */ 7 | export interface Autolink { 8 | id: number; 9 | 10 | /** 11 | * Whether this autolink reference matches alphanumeric characters. If false, this autolink reference only matches numeric characters. 12 | */ 13 | is_alphanumeric: boolean; 14 | 15 | /** 16 | * The prefix of a key that is linkified. 17 | */ 18 | key_prefix: string; 19 | 20 | /** 21 | * A template for the target URL that is generated if a key was found. 22 | */ 23 | url_template: string; 24 | } 25 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/basic-error.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Basic Error 6 | */ 7 | export interface BasicError { 8 | documentation_url?: string; 9 | message?: string; 10 | status?: string; 11 | url?: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/branch-short.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Branch Short 6 | */ 7 | export interface BranchShort { 8 | commit: { 9 | 'sha': string; 10 | 'url': string; 11 | }; 12 | name: string; 13 | protected: boolean; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/branch-with-protection.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { BranchProtection } from '../models/branch-protection'; 4 | import { Commit } from '../models/commit'; 5 | 6 | /** 7 | * Branch With Protection 8 | */ 9 | export interface BranchWithProtection { 10 | '_links': { 11 | 'html': string; 12 | 'self': string; 13 | }; 14 | commit: Commit; 15 | name: string; 16 | pattern?: string; 17 | protected: boolean; 18 | protection: BranchProtection; 19 | protection_url: string; 20 | required_approving_review_count?: number; 21 | } 22 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/check-automated-security-fixes.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Check Automated Security Fixes 6 | */ 7 | export interface CheckAutomatedSecurityFixes { 8 | 9 | /** 10 | * Whether automated security fixes are enabled for the repository. 11 | */ 12 | enabled: boolean; 13 | 14 | /** 15 | * Whether automated security fixes are paused for the repository. 16 | */ 17 | paused: boolean; 18 | } 19 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/clone-traffic.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { Traffic } from '../models/traffic'; 4 | 5 | /** 6 | * Clone Traffic 7 | */ 8 | export interface CloneTraffic { 9 | clones: Array; 10 | count: number; 11 | uniques: number; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/code-frequency-stat.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Code Frequency Stat 6 | */ 7 | export type CodeFrequencyStat = Array; 8 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/code-of-conduct-simple.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Code of Conduct Simple 6 | */ 7 | export interface CodeOfConductSimple { 8 | html_url: string | null; 9 | key: string; 10 | name: string; 11 | url: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/code-of-conduct.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Code Of Conduct 6 | */ 7 | export interface CodeOfConduct { 8 | body?: string; 9 | html_url: string | null; 10 | key: string; 11 | name: string; 12 | url: string; 13 | } 14 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/collaborator.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Collaborator 6 | */ 7 | export interface Collaborator { 8 | avatar_url: string; 9 | email?: string | null; 10 | events_url: string; 11 | followers_url: string; 12 | following_url: string; 13 | gists_url: string; 14 | gravatar_id: string | null; 15 | html_url: string; 16 | id: number; 17 | login: string; 18 | name?: string | null; 19 | node_id: string; 20 | organizations_url: string; 21 | permissions?: { 22 | 'pull': boolean; 23 | 'triage'?: boolean; 24 | 'push': boolean; 25 | 'maintain'?: boolean; 26 | 'admin': boolean; 27 | }; 28 | received_events_url: string; 29 | repos_url: string; 30 | role_name: string; 31 | site_admin: boolean; 32 | starred_url: string; 33 | subscriptions_url: string; 34 | type: string; 35 | url: string; 36 | } 37 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/combined-commit-status.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { MinimalRepository } from '../models/minimal-repository'; 4 | import { SimpleCommitStatus } from '../models/simple-commit-status'; 5 | 6 | /** 7 | * Combined Commit Status 8 | */ 9 | export interface CombinedCommitStatus { 10 | commit_url: string; 11 | repository: MinimalRepository; 12 | sha: string; 13 | state: string; 14 | statuses: Array; 15 | total_count: number; 16 | url: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/commit-activity.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Commit Activity 6 | */ 7 | export interface CommitActivity { 8 | days: Array; 9 | total: number; 10 | week: number; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/commit-comment.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { AuthorAssociation } from '../models/author-association'; 4 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 5 | import { ReactionRollup } from '../models/reaction-rollup'; 6 | 7 | /** 8 | * Commit Comment 9 | */ 10 | export interface CommitComment { 11 | author_association: AuthorAssociation; 12 | body: string; 13 | commit_id: string; 14 | created_at: string; 15 | html_url: string; 16 | id: number; 17 | line: number | null; 18 | node_id: string; 19 | path: string | null; 20 | position: number | null; 21 | reactions?: ReactionRollup; 22 | updated_at: string; 23 | url: string; 24 | user: NullableSimpleUser | null; 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/commit-comparison.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { Commit } from '../models/commit'; 4 | import { DiffEntry } from '../models/diff-entry'; 5 | 6 | /** 7 | * Commit Comparison 8 | */ 9 | export interface CommitComparison { 10 | ahead_by: number; 11 | base_commit: Commit; 12 | behind_by: number; 13 | commits: Array; 14 | diff_url: string; 15 | files?: Array; 16 | html_url: string; 17 | merge_base_commit: Commit; 18 | patch_url: string; 19 | permalink_url: string; 20 | status: 'diverged' | 'ahead' | 'behind' | 'identical'; 21 | total_commits: number; 22 | url: string; 23 | } 24 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/community-profile.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableCodeOfConductSimple } from '../models/nullable-code-of-conduct-simple'; 4 | import { NullableCommunityHealthFile } from '../models/nullable-community-health-file'; 5 | import { NullableLicenseSimple } from '../models/nullable-license-simple'; 6 | 7 | /** 8 | * Community Profile 9 | */ 10 | export interface CommunityProfile { 11 | content_reports_enabled?: boolean; 12 | description: string | null; 13 | documentation: string | null; 14 | files: { 15 | 'code_of_conduct': NullableCodeOfConductSimple | null; 16 | 'code_of_conduct_file': NullableCommunityHealthFile | null; 17 | 'license': NullableLicenseSimple | null; 18 | 'contributing': NullableCommunityHealthFile | null; 19 | 'readme': NullableCommunityHealthFile | null; 20 | 'issue_template': NullableCommunityHealthFile | null; 21 | 'pull_request_template': NullableCommunityHealthFile | null; 22 | }; 23 | health_percentage: number; 24 | updated_at: string | null; 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/content-directory.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * A list of directory items 6 | */ 7 | export type ContentDirectory = Array<{ 8 | 'type': 'dir' | 'file' | 'submodule' | 'symlink'; 9 | 'size': number; 10 | 'name': string; 11 | 'path': string; 12 | 'content'?: string; 13 | 'sha': string; 14 | 'url': string; 15 | 'git_url': string | null; 16 | 'html_url': string | null; 17 | 'download_url': string | null; 18 | '_links': { 19 | 'git': string | null; 20 | 'html': string | null; 21 | 'self': string; 22 | }; 23 | }>; 24 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/content-file.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Content File 6 | */ 7 | export interface ContentFile { 8 | '_links': { 9 | 'git': string | null; 10 | 'html': string | null; 11 | 'self': string; 12 | }; 13 | content: string; 14 | download_url: string | null; 15 | encoding: string; 16 | git_url: string | null; 17 | html_url: string | null; 18 | name: string; 19 | path: string; 20 | sha: string; 21 | size: number; 22 | submodule_git_url?: string; 23 | target?: string; 24 | type: 'file'; 25 | url: string; 26 | } 27 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/content-submodule.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * An object describing a submodule 6 | */ 7 | export interface ContentSubmodule { 8 | '_links': { 9 | 'git': string | null; 10 | 'html': string | null; 11 | 'self': string; 12 | }; 13 | download_url: string | null; 14 | git_url: string | null; 15 | html_url: string | null; 16 | name: string; 17 | path: string; 18 | sha: string; 19 | size: number; 20 | submodule_git_url: string; 21 | type: 'submodule'; 22 | url: string; 23 | } 24 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/content-symlink.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * An object describing a symlink 6 | */ 7 | export interface ContentSymlink { 8 | '_links': { 9 | 'git': string | null; 10 | 'html': string | null; 11 | 'self': string; 12 | }; 13 | download_url: string | null; 14 | git_url: string | null; 15 | html_url: string | null; 16 | name: string; 17 | path: string; 18 | sha: string; 19 | size: number; 20 | target: string; 21 | type: 'symlink'; 22 | url: string; 23 | } 24 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/content-traffic.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Content Traffic 6 | */ 7 | export interface ContentTraffic { 8 | count: number; 9 | path: string; 10 | title: string; 11 | uniques: number; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/content-tree.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Content Tree 6 | */ 7 | export interface ContentTree { 8 | '_links': { 9 | 'git': string | null; 10 | 'html': string | null; 11 | 'self': string; 12 | }; 13 | download_url: string | null; 14 | entries?: Array<{ 15 | 'type': string; 16 | 'size': number; 17 | 'name': string; 18 | 'path': string; 19 | 'content'?: string; 20 | 'sha': string; 21 | 'url': string; 22 | 'git_url': string | null; 23 | 'html_url': string | null; 24 | 'download_url': string | null; 25 | '_links': { 26 | 'git': string | null; 27 | 'html': string | null; 28 | 'self': string; 29 | }; 30 | }>; 31 | git_url: string | null; 32 | html_url: string | null; 33 | name: string; 34 | path: string; 35 | sha: string; 36 | size: number; 37 | type: string; 38 | url: string; 39 | } 40 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/contributor-activity.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 4 | 5 | /** 6 | * Contributor Activity 7 | */ 8 | export interface ContributorActivity { 9 | author: NullableSimpleUser | null; 10 | total: number; 11 | weeks: Array<{ 12 | 'w'?: number; 13 | 'a'?: number; 14 | 'd'?: number; 15 | 'c'?: number; 16 | }>; 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/contributor.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Contributor 6 | */ 7 | export interface Contributor { 8 | avatar_url?: string; 9 | contributions: number; 10 | email?: string; 11 | events_url?: string; 12 | followers_url?: string; 13 | following_url?: string; 14 | gists_url?: string; 15 | gravatar_id?: string | null; 16 | html_url?: string; 17 | id?: number; 18 | login?: string; 19 | name?: string; 20 | node_id?: string; 21 | organizations_url?: string; 22 | received_events_url?: string; 23 | repos_url?: string; 24 | site_admin?: boolean; 25 | starred_url?: string; 26 | subscriptions_url?: string; 27 | type: string; 28 | url?: string; 29 | } 30 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/custom-deployment-rule-app.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * A GitHub App that is providing a custom deployment protection rule. 6 | */ 7 | export interface CustomDeploymentRuleApp { 8 | 9 | /** 10 | * The unique identifier of the deployment protection rule integration. 11 | */ 12 | id: number; 13 | 14 | /** 15 | * The URL for the endpoint to get details about the app. 16 | */ 17 | integration_url: string; 18 | 19 | /** 20 | * The node ID for the deployment protection rule integration. 21 | */ 22 | node_id: string; 23 | 24 | /** 25 | * The slugified name of the deployment protection rule integration. 26 | */ 27 | slug: string; 28 | } 29 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/deploy-key.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * An SSH key granting access to a single repository. 6 | */ 7 | export interface DeployKey { 8 | added_by?: string | null; 9 | created_at: string; 10 | id: number; 11 | key: string; 12 | last_used?: string | null; 13 | read_only: boolean; 14 | title: string; 15 | url: string; 16 | verified: boolean; 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/deployment-branch-policy-name-pattern.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface DeploymentBranchPolicyNamePattern { 4 | 5 | /** 6 | * The name pattern that branches must match in order to deploy to the environment. 7 | * 8 | * Wildcard characters will not match `/`. For example, to match branches that begin with `release/` and contain an additional single slash, use `release/* / *`. 9 | * For more information about pattern matching syntax, see the [Ruby File.fnmatch documentation](https://ruby-doc.org/core-2.5.1/File.html#method-c-fnmatch). 10 | */ 11 | name: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/deployment-branch-policy-settings.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * The type of deployment branch policy for this environment. To allow all branches to deploy, set to `null`. 6 | */ 7 | export type DeploymentBranchPolicySettings = ({ 8 | 9 | /** 10 | * Whether only branches with branch protection rules can deploy to this environment. If `protected_branches` is `true`, `custom_branch_policies` must be `false`; if `protected_branches` is `false`, `custom_branch_policies` must be `true`. 11 | */ 12 | 'protected_branches': boolean; 13 | 14 | /** 15 | * Whether only branches that match the specified name patterns can deploy to this environment. If `custom_branch_policies` is `true`, `protected_branches` must be `false`; if `custom_branch_policies` is `false`, `protected_branches` must be `true`. 16 | */ 17 | 'custom_branch_policies': boolean; 18 | }) | null; 19 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/deployment-branch-policy.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Details of a deployment branch policy. 6 | */ 7 | export interface DeploymentBranchPolicy { 8 | 9 | /** 10 | * The unique identifier of the branch policy. 11 | */ 12 | id?: number; 13 | 14 | /** 15 | * The name pattern that branches must match in order to deploy to the environment. 16 | */ 17 | name?: string; 18 | node_id?: string; 19 | } 20 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/deployment-protection-rule.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { CustomDeploymentRuleApp } from '../models/custom-deployment-rule-app'; 4 | 5 | /** 6 | * Deployment protection rule 7 | */ 8 | export interface DeploymentProtectionRule { 9 | app: CustomDeploymentRuleApp; 10 | 11 | /** 12 | * Whether the deployment protection rule is enabled for the environment. 13 | */ 14 | enabled: boolean; 15 | 16 | /** 17 | * The unique identifier for the deployment protection rule. 18 | */ 19 | id: number; 20 | 21 | /** 22 | * The node ID for the deployment protection rule. 23 | */ 24 | node_id: string; 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/deployment-reviewer-type.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * The type of reviewer. 6 | */ 7 | export enum DeploymentReviewerType { 8 | User = 'User', 9 | Team = 'Team' 10 | } 11 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/diff-entry.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Diff Entry 6 | */ 7 | export interface DiffEntry { 8 | additions: number; 9 | blob_url: string; 10 | changes: number; 11 | contents_url: string; 12 | deletions: number; 13 | filename: string; 14 | patch?: string; 15 | previous_filename?: string; 16 | raw_url: string; 17 | sha: string; 18 | status: 'added' | 'removed' | 'modified' | 'renamed' | 'copied' | 'changed' | 'unchanged'; 19 | } 20 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/empty-object.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * An object without any properties. 6 | */ 7 | export interface EmptyObject { 8 | } 9 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/hook-response.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface HookResponse { 4 | code: number | null; 5 | message: string | null; 6 | status: string | null; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/language.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Language 6 | */ 7 | export interface Language { 8 | 9 | [key: string]: number; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/link.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Hypermedia Link 6 | */ 7 | export interface Link { 8 | href: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/merged-upstream.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Results of a successful merge upstream request 6 | */ 7 | export interface MergedUpstream { 8 | base_branch?: string; 9 | merge_type?: 'merge' | 'fast-forward' | 'none'; 10 | message?: string; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/nullable-code-of-conduct-simple.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Code of Conduct Simple 6 | */ 7 | export type NullableCodeOfConductSimple = { 8 | 'url': string; 9 | 'key': string; 10 | 'name': string; 11 | 'html_url': string | null; 12 | }; 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/nullable-collaborator.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Collaborator 6 | */ 7 | export type NullableCollaborator = { 8 | 'login': string; 9 | 'id': number; 10 | 'email'?: string | null; 11 | 'name'?: string | null; 12 | 'node_id': string; 13 | 'avatar_url': string; 14 | 'gravatar_id': string | null; 15 | 'url': string; 16 | 'html_url': string; 17 | 'followers_url': string; 18 | 'following_url': string; 19 | 'gists_url': string; 20 | 'starred_url': string; 21 | 'subscriptions_url': string; 22 | 'organizations_url': string; 23 | 'repos_url': string; 24 | 'events_url': string; 25 | 'received_events_url': string; 26 | 'type': string; 27 | 'site_admin': boolean; 28 | 'permissions'?: { 29 | 'pull': boolean; 30 | 'triage'?: boolean; 31 | 'push': boolean; 32 | 'maintain'?: boolean; 33 | 'admin': boolean; 34 | }; 35 | 'role_name': string; 36 | }; 37 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/nullable-community-health-file.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export type NullableCommunityHealthFile = ({ 4 | 'url': string; 5 | 'html_url': string; 6 | }) | null; 7 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/nullable-git-user.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Metaproperties for Git author/committer information. 6 | */ 7 | export type NullableGitUser = ({ 8 | 'name'?: string; 9 | 'email'?: string; 10 | 'date'?: string; 11 | }) | null; 12 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/nullable-license-simple.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * License Simple 6 | */ 7 | export type NullableLicenseSimple = { 8 | 'key': string; 9 | 'name': string; 10 | 'url': string | null; 11 | 'spdx_id': string | null; 12 | 'node_id': string; 13 | 'html_url'?: string; 14 | }; 15 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/nullable-milestone.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 4 | 5 | /** 6 | * A collection of related issues and pull requests. 7 | */ 8 | export type NullableMilestone = { 9 | 'url': string; 10 | 'html_url': string; 11 | 'labels_url': string; 12 | 'id': number; 13 | 'node_id': string; 14 | 15 | /** 16 | * The number of the milestone. 17 | */ 18 | 'number': number; 19 | 20 | /** 21 | * The state of the milestone. 22 | */ 23 | 'state': 'open' | 'closed'; 24 | 25 | /** 26 | * The title of the milestone. 27 | */ 28 | 'title': string; 29 | 'description': string | null; 30 | 'creator': NullableSimpleUser | null; 31 | 'open_issues': number; 32 | 'closed_issues': number; 33 | 'created_at': string; 34 | 'updated_at': string; 35 | 'closed_at': string | null; 36 | 'due_on': string | null; 37 | }; 38 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/nullable-simple-user.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * A GitHub user. 6 | */ 7 | export type NullableSimpleUser = { 8 | 'name'?: string | null; 9 | 'email'?: string | null; 10 | 'login': string; 11 | 'id': number; 12 | 'node_id': string; 13 | 'avatar_url': string; 14 | 'gravatar_id': string | null; 15 | 'url': string; 16 | 'html_url': string; 17 | 'followers_url': string; 18 | 'following_url': string; 19 | 'gists_url': string; 20 | 'starred_url': string; 21 | 'subscriptions_url': string; 22 | 'organizations_url': string; 23 | 'repos_url': string; 24 | 'events_url': string; 25 | 'received_events_url': string; 26 | 'type': string; 27 | 'site_admin': boolean; 28 | 'starred_at'?: string; 29 | }; 30 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/org-ruleset-conditions.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { RepositoryRulesetConditions } from '../models/repository-ruleset-conditions'; 4 | import { RepositoryRulesetConditionsRepositoryIdTarget } from '../models/repository-ruleset-conditions-repository-id-target'; 5 | import { RepositoryRulesetConditionsRepositoryNameTarget } from '../models/repository-ruleset-conditions-repository-name-target'; 6 | 7 | /** 8 | * Conditions for an organization ruleset. The conditions object should contain both `repository_name` and `ref_name` properties or both `repository_id` and `ref_name` properties. 9 | */ 10 | export type OrgRulesetConditions = (RepositoryRulesetConditions & RepositoryRulesetConditionsRepositoryNameTarget & { 11 | } | RepositoryRulesetConditions & RepositoryRulesetConditionsRepositoryIdTarget & { 12 | }); 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/page-build-status.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Page Build Status 6 | */ 7 | export interface PageBuildStatus { 8 | status: string; 9 | url: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/page-build.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 4 | 5 | /** 6 | * Page Build 7 | */ 8 | export interface PageBuild { 9 | commit: string; 10 | created_at: string; 11 | duration: number; 12 | error: { 13 | 'message': string | null; 14 | }; 15 | pusher: NullableSimpleUser | null; 16 | status: string; 17 | updated_at: string; 18 | url: string; 19 | } 20 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/page-deployment.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * The GitHub Pages deployment status. 6 | */ 7 | export interface PageDeployment { 8 | 9 | /** 10 | * The URI to the deployed GitHub Pages. 11 | */ 12 | page_url: string; 13 | 14 | /** 15 | * The URI to the deployed GitHub Pages preview. 16 | */ 17 | preview_url?: string; 18 | 19 | /** 20 | * The URI to monitor GitHub Pages deployment status. 21 | */ 22 | status_url: string; 23 | } 24 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/pages-https-certificate.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface PagesHttpsCertificate { 4 | description: string; 5 | 6 | /** 7 | * Array of the domain set and its alternate name (if it is configured) 8 | */ 9 | domains: Array; 10 | expires_at?: string; 11 | state: 'new' | 'authorization_created' | 'authorization_pending' | 'authorized' | 'authorization_revoked' | 'issued' | 'uploaded' | 'approved' | 'errored' | 'bad_authz' | 'destroy_pending' | 'dns_changed'; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/pages-source-hash.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface PagesSourceHash { 4 | branch: string; 5 | path: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/participation-stats.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface ParticipationStats { 4 | all: Array; 5 | owner: Array; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/protected-branch-admin-enforced.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Protected Branch Admin Enforced 6 | */ 7 | export interface ProtectedBranchAdminEnforced { 8 | enabled: boolean; 9 | url: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/protected-branch-required-status-check.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Protected Branch Required Status Check 6 | */ 7 | export interface ProtectedBranchRequiredStatusCheck { 8 | checks: Array<{ 9 | 'context': string; 10 | 'app_id': number | null; 11 | }>; 12 | contexts: Array; 13 | contexts_url?: string; 14 | enforcement_level?: string; 15 | strict?: boolean; 16 | url?: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/reaction-rollup.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface ReactionRollup { 4 | '+1': number; 5 | '-1': number; 6 | confused: number; 7 | eyes: number; 8 | heart: number; 9 | hooray: number; 10 | laugh: number; 11 | rocket: number; 12 | total_count: number; 13 | url: string; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/referrer-traffic.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Referrer Traffic 6 | */ 7 | export interface ReferrerTraffic { 8 | count: number; 9 | referrer: string; 10 | uniques: number; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/release-asset.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 4 | 5 | /** 6 | * Data related to a release. 7 | */ 8 | export interface ReleaseAsset { 9 | browser_download_url: string; 10 | content_type: string; 11 | created_at: string; 12 | download_count: number; 13 | id: number; 14 | label: string | null; 15 | 16 | /** 17 | * The file name of the asset. 18 | */ 19 | name: string; 20 | node_id: string; 21 | size: number; 22 | 23 | /** 24 | * State of the release asset. 25 | */ 26 | state: 'uploaded' | 'open'; 27 | updated_at: string; 28 | uploader: NullableSimpleUser | null; 29 | url: string; 30 | } 31 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/release-notes-content.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Generated name and body describing a release 6 | */ 7 | export interface ReleaseNotesContent { 8 | 9 | /** 10 | * The generated body describing the contents of the release supporting markdown formatting 11 | */ 12 | body: string; 13 | 14 | /** 15 | * The generated name of the release 16 | */ 17 | name: string; 18 | } 19 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-collaborator-permission.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableCollaborator } from '../models/nullable-collaborator'; 4 | 5 | /** 6 | * Repository Collaborator Permission 7 | */ 8 | export interface RepositoryCollaboratorPermission { 9 | permission: string; 10 | role_name: string; 11 | user: NullableCollaborator | null; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-invitation.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { MinimalRepository } from '../models/minimal-repository'; 4 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 5 | 6 | /** 7 | * Repository invitations let you manage who you collaborate with. 8 | */ 9 | export interface RepositoryInvitation { 10 | created_at: string; 11 | 12 | /** 13 | * Whether or not the invitation has expired 14 | */ 15 | expired?: boolean; 16 | html_url: string; 17 | 18 | /** 19 | * Unique identifier of the repository invitation. 20 | */ 21 | id: number; 22 | invitee: NullableSimpleUser | null; 23 | inviter: NullableSimpleUser | null; 24 | node_id: string; 25 | 26 | /** 27 | * The permission associated with the invitation. 28 | */ 29 | permissions: 'read' | 'write' | 'admin' | 'triage' | 'maintain'; 30 | repository: MinimalRepository; 31 | 32 | /** 33 | * URL for the repository invitation 34 | */ 35 | url: string; 36 | } 37 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-branch-name-pattern.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters to be used for the branch_name_pattern rule 6 | */ 7 | export interface RepositoryRuleBranchNamePattern { 8 | parameters?: { 9 | 10 | /** 11 | * How this rule will appear to users. 12 | */ 13 | 'name'?: string; 14 | 15 | /** 16 | * If true, the rule will fail if the pattern matches. 17 | */ 18 | 'negate'?: boolean; 19 | 20 | /** 21 | * The operator to use for matching. 22 | */ 23 | 'operator': 'starts_with' | 'ends_with' | 'contains' | 'regex'; 24 | 25 | /** 26 | * The pattern to match with. 27 | */ 28 | 'pattern': string; 29 | }; 30 | type: 'branch_name_pattern'; 31 | } 32 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-commit-author-email-pattern.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters to be used for the commit_author_email_pattern rule 6 | */ 7 | export interface RepositoryRuleCommitAuthorEmailPattern { 8 | parameters?: { 9 | 10 | /** 11 | * How this rule will appear to users. 12 | */ 13 | 'name'?: string; 14 | 15 | /** 16 | * If true, the rule will fail if the pattern matches. 17 | */ 18 | 'negate'?: boolean; 19 | 20 | /** 21 | * The operator to use for matching. 22 | */ 23 | 'operator': 'starts_with' | 'ends_with' | 'contains' | 'regex'; 24 | 25 | /** 26 | * The pattern to match with. 27 | */ 28 | 'pattern': string; 29 | }; 30 | type: 'commit_author_email_pattern'; 31 | } 32 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-commit-message-pattern.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters to be used for the commit_message_pattern rule 6 | */ 7 | export interface RepositoryRuleCommitMessagePattern { 8 | parameters?: { 9 | 10 | /** 11 | * How this rule will appear to users. 12 | */ 13 | 'name'?: string; 14 | 15 | /** 16 | * If true, the rule will fail if the pattern matches. 17 | */ 18 | 'negate'?: boolean; 19 | 20 | /** 21 | * The operator to use for matching. 22 | */ 23 | 'operator': 'starts_with' | 'ends_with' | 'contains' | 'regex'; 24 | 25 | /** 26 | * The pattern to match with. 27 | */ 28 | 'pattern': string; 29 | }; 30 | type: 'commit_message_pattern'; 31 | } 32 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-committer-email-pattern.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters to be used for the committer_email_pattern rule 6 | */ 7 | export interface RepositoryRuleCommitterEmailPattern { 8 | parameters?: { 9 | 10 | /** 11 | * How this rule will appear to users. 12 | */ 13 | 'name'?: string; 14 | 15 | /** 16 | * If true, the rule will fail if the pattern matches. 17 | */ 18 | 'negate'?: boolean; 19 | 20 | /** 21 | * The operator to use for matching. 22 | */ 23 | 'operator': 'starts_with' | 'ends_with' | 'contains' | 'regex'; 24 | 25 | /** 26 | * The pattern to match with. 27 | */ 28 | 'pattern': string; 29 | }; 30 | type: 'committer_email_pattern'; 31 | } 32 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-creation.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Only allow users with bypass permission to create matching refs. 6 | */ 7 | export interface RepositoryRuleCreation { 8 | type: 'creation'; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-deletion.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Only allow users with bypass permissions to delete matching refs. 6 | */ 7 | export interface RepositoryRuleDeletion { 8 | type: 'deletion'; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-enforcement.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * The enforcement level of the ruleset. `evaluate` allows admins to test rules before enforcing them. Admins can view insights on the Rule Insights page (`evaluate` is only available with GitHub Enterprise). 6 | */ 7 | export enum RepositoryRuleEnforcement { 8 | Disabled = 'disabled', 9 | Active = 'active', 10 | Evaluate = 'evaluate' 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-non-fast-forward.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Prevent users with push access from force pushing to branches. 6 | */ 7 | export interface RepositoryRuleNonFastForward { 8 | type: 'non_fast_forward'; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-params-status-check-configuration.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Required status check 6 | */ 7 | export interface RepositoryRuleParamsStatusCheckConfiguration { 8 | 9 | /** 10 | * The status check context name that must be present on the commit. 11 | */ 12 | context: string; 13 | 14 | /** 15 | * The optional integration ID that this status check must originate from. 16 | */ 17 | integration_id?: number; 18 | } 19 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-required-deployments.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Choose which environments must be successfully deployed to before branches can be merged into a branch that matches this rule. 6 | */ 7 | export interface RepositoryRuleRequiredDeployments { 8 | parameters?: { 9 | 10 | /** 11 | * The environments that must be successfully deployed to before branches can be merged. 12 | */ 13 | 'required_deployment_environments': Array; 14 | }; 15 | type: 'required_deployments'; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-required-linear-history.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Prevent merge commits from being pushed to matching branches. 6 | */ 7 | export interface RepositoryRuleRequiredLinearHistory { 8 | type: 'required_linear_history'; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-required-signatures.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Commits pushed to matching branches must have verified signatures. 6 | */ 7 | export interface RepositoryRuleRequiredSignatures { 8 | type: 'required_signatures'; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-required-status-checks.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { RepositoryRuleParamsStatusCheckConfiguration } from '../models/repository-rule-params-status-check-configuration'; 4 | 5 | /** 6 | * Choose which status checks must pass before branches can be merged into a branch that matches this rule. When enabled, commits must first be pushed to another branch, then merged or pushed directly to a branch that matches this rule after status checks have passed. 7 | */ 8 | export interface RepositoryRuleRequiredStatusChecks { 9 | parameters?: { 10 | 11 | /** 12 | * Status checks that are required. 13 | */ 14 | 'required_status_checks': Array; 15 | 16 | /** 17 | * Whether pull requests targeting a matching branch must be tested with the latest code. This setting will not take effect unless at least one status check is enabled. 18 | */ 19 | 'strict_required_status_checks_policy': boolean; 20 | }; 21 | type: 'required_status_checks'; 22 | } 23 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-ruleset-info.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * User-defined metadata to store domain-specific information limited to 8 keys with scalar values. 6 | */ 7 | export interface RepositoryRuleRulesetInfo { 8 | 9 | /** 10 | * The ID of the ruleset that includes this rule. 11 | */ 12 | ruleset_id?: number; 13 | 14 | /** 15 | * The name of the source of the ruleset that includes this rule. 16 | */ 17 | ruleset_source?: string; 18 | 19 | /** 20 | * The type of source for the ruleset that includes this rule. 21 | */ 22 | ruleset_source_type?: 'Repository' | 'Organization'; 23 | } 24 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-tag-name-pattern.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters to be used for the tag_name_pattern rule 6 | */ 7 | export interface RepositoryRuleTagNamePattern { 8 | parameters?: { 9 | 10 | /** 11 | * How this rule will appear to users. 12 | */ 13 | 'name'?: string; 14 | 15 | /** 16 | * If true, the rule will fail if the pattern matches. 17 | */ 18 | 'negate'?: boolean; 19 | 20 | /** 21 | * The operator to use for matching. 22 | */ 23 | 'operator': 'starts_with' | 'ends_with' | 'contains' | 'regex'; 24 | 25 | /** 26 | * The pattern to match with. 27 | */ 28 | 'pattern': string; 29 | }; 30 | type: 'tag_name_pattern'; 31 | } 32 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-rule-update.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Only allow users with bypass permission to update matching refs. 6 | */ 7 | export interface RepositoryRuleUpdate { 8 | parameters?: { 9 | 10 | /** 11 | * Branch can pull changes from its upstream repository 12 | */ 13 | 'update_allows_fetch_and_merge': boolean; 14 | }; 15 | type: 'update'; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-ruleset-bypass-actor.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * An actor that can bypass rules in a ruleset 6 | */ 7 | export interface RepositoryRulesetBypassActor { 8 | 9 | /** 10 | * The ID of the actor that can bypass a ruleset 11 | */ 12 | actor_id: number; 13 | 14 | /** 15 | * The type of actor that can bypass a ruleset 16 | */ 17 | actor_type: 'RepositoryRole' | 'Team' | 'Integration' | 'OrganizationAdmin'; 18 | 19 | /** 20 | * When the specified actor can bypass the ruleset. `pull_request` means that an actor can only bypass rules on pull requests. 21 | */ 22 | bypass_mode: 'always' | 'pull_request'; 23 | } 24 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-ruleset-conditions-repository-id-target.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters for a repository ID condition 6 | */ 7 | export interface RepositoryRulesetConditionsRepositoryIdTarget { 8 | repository_id: { 9 | 10 | /** 11 | * The repository IDs that the ruleset applies to. One of these IDs must match for the condition to pass. 12 | */ 13 | 'repository_ids'?: Array; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-ruleset-conditions-repository-name-target.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters for a repository name condition 6 | */ 7 | export interface RepositoryRulesetConditionsRepositoryNameTarget { 8 | repository_name: { 9 | 10 | /** 11 | * Array of repository names or patterns to include. One of these patterns must match for the condition to pass. Also accepts `~ALL` to include all repositories. 12 | */ 13 | 'include'?: Array; 14 | 15 | /** 16 | * Array of repository names or patterns to exclude. The condition will not pass if any of these patterns match. 17 | */ 18 | 'exclude'?: Array; 19 | 20 | /** 21 | * Whether renaming of target repositories is prevented. 22 | */ 23 | 'protected'?: boolean; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/repository-ruleset-conditions.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Parameters for a repository ruleset ref name condition 6 | */ 7 | export interface RepositoryRulesetConditions { 8 | ref_name?: { 9 | 10 | /** 11 | * Array of ref names or patterns to include. One of these patterns must match for the condition to pass. Also accepts `~DEFAULT_BRANCH` to include the default branch or `~ALL` to include all branches. 12 | */ 13 | 'include'?: Array; 14 | 15 | /** 16 | * Array of ref names or patterns to exclude. The condition will not pass if any of these patterns match. 17 | */ 18 | 'exclude'?: Array; 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/scim-error.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Scim Error 6 | */ 7 | export interface ScimError { 8 | detail?: string | null; 9 | documentation_url?: string | null; 10 | message?: string | null; 11 | schemas?: Array; 12 | scimType?: string | null; 13 | status?: number; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/security-and-analysis.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export type SecurityAndAnalysis = ({ 4 | 'advanced_security'?: { 5 | 'status'?: 'enabled' | 'disabled'; 6 | }; 7 | 8 | /** 9 | * Enable or disable Dependabot security updates for the repository. 10 | */ 11 | 'dependabot_security_updates'?: { 12 | 13 | /** 14 | * The enablement status of Dependabot security updates for the repository. 15 | */ 16 | 'status'?: 'enabled' | 'disabled'; 17 | }; 18 | 'secret_scanning'?: { 19 | 'status'?: 'enabled' | 'disabled'; 20 | }; 21 | 'secret_scanning_push_protection'?: { 22 | 'status'?: 'enabled' | 'disabled'; 23 | }; 24 | }) | null; 25 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/short-branch.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { BranchProtection } from '../models/branch-protection'; 4 | 5 | /** 6 | * Short Branch 7 | */ 8 | export interface ShortBranch { 9 | commit: { 10 | 'sha': string; 11 | 'url': string; 12 | }; 13 | name: string; 14 | protected: boolean; 15 | protection?: BranchProtection; 16 | protection_url?: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/simple-commit-status.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface SimpleCommitStatus { 4 | avatar_url: string | null; 5 | context: string; 6 | created_at: string; 7 | description: string | null; 8 | id: number; 9 | node_id: string; 10 | required?: boolean | null; 11 | state: string; 12 | target_url: string | null; 13 | updated_at: string; 14 | url: string; 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/simple-user.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * A GitHub user. 6 | */ 7 | export interface SimpleUser { 8 | avatar_url: string; 9 | email?: string | null; 10 | events_url: string; 11 | followers_url: string; 12 | following_url: string; 13 | gists_url: string; 14 | gravatar_id: string | null; 15 | html_url: string; 16 | id: number; 17 | login: string; 18 | name?: string | null; 19 | node_id: string; 20 | organizations_url: string; 21 | received_events_url: string; 22 | repos_url: string; 23 | site_admin: boolean; 24 | starred_at?: string; 25 | starred_url: string; 26 | subscriptions_url: string; 27 | type: string; 28 | url: string; 29 | } 30 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/status-check-policy.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Status Check Policy 6 | */ 7 | export interface StatusCheckPolicy { 8 | checks: Array<{ 9 | 'context': string; 10 | 'app_id': number | null; 11 | }>; 12 | contexts: Array; 13 | contexts_url: string; 14 | strict: boolean; 15 | url: string; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/status.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableSimpleUser } from '../models/nullable-simple-user'; 4 | 5 | /** 6 | * The status of a commit. 7 | */ 8 | export interface Status { 9 | avatar_url: string | null; 10 | context: string; 11 | created_at: string; 12 | creator: NullableSimpleUser | null; 13 | description: string | null; 14 | id: number; 15 | node_id: string; 16 | state: string; 17 | target_url: string | null; 18 | updated_at: string; 19 | url: string; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/tag-protection.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Tag protection 6 | */ 7 | export interface TagProtection { 8 | created_at?: string; 9 | enabled?: boolean; 10 | id?: number; 11 | pattern: string; 12 | updated_at?: string; 13 | } 14 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/tag.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Tag 6 | */ 7 | export interface Tag { 8 | commit: { 9 | 'sha': string; 10 | 'url': string; 11 | }; 12 | name: string; 13 | node_id: string; 14 | tarball_url: string; 15 | zipball_url: string; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/team.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { NullableTeamSimple } from '../models/nullable-team-simple'; 4 | 5 | /** 6 | * Groups of organization members that gives permissions on specified repositories. 7 | */ 8 | export interface Team { 9 | description: string | null; 10 | html_url: string; 11 | id: number; 12 | members_url: string; 13 | name: string; 14 | node_id: string; 15 | notification_setting?: string; 16 | parent: NullableTeamSimple | null; 17 | permission: string; 18 | permissions?: { 19 | 'pull': boolean; 20 | 'triage': boolean; 21 | 'push': boolean; 22 | 'maintain': boolean; 23 | 'admin': boolean; 24 | }; 25 | privacy?: string; 26 | repositories_url: string; 27 | slug: string; 28 | url: string; 29 | } 30 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/topic.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * A topic aggregates entities that are related to a subject. 6 | */ 7 | export interface Topic { 8 | names: Array; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/traffic.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface Traffic { 4 | count: number; 5 | timestamp: string; 6 | uniques: number; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/validation-error-simple.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Validation Error Simple 6 | */ 7 | export interface ValidationErrorSimple { 8 | documentation_url: string; 9 | errors?: Array; 10 | message: string; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/validation-error.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * Validation Error 6 | */ 7 | export interface ValidationError { 8 | documentation_url: string; 9 | errors?: Array<{ 10 | 'resource'?: string; 11 | 'field'?: string; 12 | 'message'?: string; 13 | 'code': string; 14 | 'index'?: number; 15 | 'value'?: (string | null | number | null | Array | null); 16 | }>; 17 | message: string; 18 | } 19 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/verification.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export interface Verification { 4 | payload: string | null; 5 | reason: string; 6 | signature: string | null; 7 | verified: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/view-traffic.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { Traffic } from '../models/traffic'; 4 | 5 | /** 6 | * View Traffic 7 | */ 8 | export interface ViewTraffic { 9 | count: number; 10 | uniques: number; 11 | views: Array; 12 | } 13 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/wait-timer.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * The amount of time to delay a job after the job is initially triggered. The time (in minutes) must be an integer between 0 and 43,200 (30 days). 6 | */ 7 | export type WaitTimer = number; 8 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/webhook-config-content-type.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * The media type used to serialize the payloads. Supported values include `json` and `form`. The default is `form`. 6 | */ 7 | export type WebhookConfigContentType = string; 8 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/webhook-config-insecure-ssl.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export type WebhookConfigInsecureSsl = (string | number); 4 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/webhook-config-secret.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * If provided, the `secret` will be used as the `key` to generate the HMAC hex digest value for [delivery signature headers](https://docs.github.com/webhooks/event-payloads/#delivery-headers). 6 | */ 7 | export type WebhookConfigSecret = string; 8 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/webhook-config-url.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /** 5 | * The URL to which the payloads will be delivered. 6 | */ 7 | export type WebhookConfigUrl = string; 8 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/models/webhook-config.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { WebhookConfigContentType } from '../models/webhook-config-content-type'; 4 | import { WebhookConfigInsecureSsl } from '../models/webhook-config-insecure-ssl'; 5 | import { WebhookConfigSecret } from '../models/webhook-config-secret'; 6 | import { WebhookConfigUrl } from '../models/webhook-config-url'; 7 | 8 | /** 9 | * Configuration object of the webhook 10 | */ 11 | export interface WebhookConfig { 12 | content_type?: WebhookConfigContentType; 13 | insecure_ssl?: WebhookConfigInsecureSsl; 14 | secret?: WebhookConfigSecret; 15 | url?: WebhookConfigUrl; 16 | } 17 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/services.ts: -------------------------------------------------------------------------------- 1 | export { ReposService } from './services/repos.service'; 2 | -------------------------------------------------------------------------------- /src/app/shared/generated/github/strict-http-response.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | import { HttpResponse } from '@angular/common/http'; 4 | 5 | /** 6 | * Constrains the http response to not have the body defined as `T | null`, but `T` only. 7 | */ 8 | export type StrictHttpResponse = HttpResponse & { 9 | readonly body: T; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/shared/guards/dirty-form.guard.ts: -------------------------------------------------------------------------------- 1 | export interface DirtyFormGuardComponent { 2 | get isFormDirty(): boolean; 3 | } 4 | 5 | export function isFormDirtyGuard(component: T): boolean { 6 | if (component.isFormDirty) { 7 | return window.confirm('You have unsaved changes. Do you really want to leave?'); 8 | } 9 | return true; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/shared/models/locale.model.ts: -------------------------------------------------------------------------------- 1 | export interface Locale { 2 | id: string; 3 | name: string; 4 | } 5 | 6 | export const DEFAULT_LOCALE: Locale = { id: 'default', name: 'Default' }; 7 | -------------------------------------------------------------------------------- /src/app/shared/models/material.model.ts: -------------------------------------------------------------------------------- 1 | export interface MaterialIcons { 2 | host: string; 3 | asset_url_pattern: string; 4 | families: string[]; 5 | icons: MaterialIcon[]; 6 | } 7 | 8 | export interface MaterialIcon { 9 | name: string; 10 | version: number; 11 | popularity: number; 12 | codepoint: number; 13 | unsupported_families: string[]; 14 | categories: string[]; 15 | tags: string[]; 16 | sizes_px: number[]; 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/models/me.model.ts: -------------------------------------------------------------------------------- 1 | export interface MeUpdate { 2 | displayName?: string; 3 | photoURL?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/shared/models/settings.model.ts: -------------------------------------------------------------------------------- 1 | import { Timestamp } from '@angular/fire/firestore'; 2 | 3 | export interface AppSettings { 4 | // UI 5 | ui?: AppUi; 6 | 7 | updatedAt: Timestamp; 8 | } 9 | 10 | export interface AppUi { 11 | text?: string; 12 | color?: AppUiColor; 13 | } 14 | 15 | export type AppUiColor = 'primary' | 'secondary' | 'tertiary' | 'error'; 16 | 17 | export interface AppSettingsUiUpdate { 18 | text?: string; 19 | color?: AppUiColor; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/shared/models/token.model.ts: -------------------------------------------------------------------------------- 1 | import { FieldValue } from '@angular/fire/firestore'; 2 | 3 | export interface Token { 4 | id: string; 5 | name: string; 6 | createdAt: FieldValue; 7 | updatedAt: FieldValue; 8 | } 9 | 10 | export interface TokenCreateFS { 11 | name: string; 12 | createdAt: FieldValue; 13 | updatedAt: FieldValue; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/shared/models/translate.model.ts: -------------------------------------------------------------------------------- 1 | export interface TranslateData { 2 | content: string; 3 | sourceLocale: string | null; 4 | targetLocale: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/shared/pipes/digital-store.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; 4 | 5 | @Pipe({ 6 | name: 'formatFileSize', 7 | standalone: true, 8 | }) 9 | export class FormatFileSizePipe implements PipeTransform { 10 | transform(bytes?: number): string { 11 | if (bytes != undefined) { 12 | let size = bytes; 13 | let unitIndex = 0; 14 | while (size >= 1024 && unitIndex < units.length - 1) { 15 | size /= 1024; 16 | unitIndex++; 17 | } 18 | return `${size.toFixed(2)} ${units[unitIndex]}`; 19 | } 20 | return ''; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/shared/pipes/time-duration.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | const MINUTE = 60; 4 | const HOUR = 60 * MINUTE; 5 | 6 | @Pipe({ 7 | name: 'timeDuration', 8 | standalone: true, 9 | }) 10 | export class TimeDurationPipe implements PipeTransform { 11 | transform(duration?: number): string { 12 | if (duration != undefined) { 13 | const hours = Math.trunc(duration / HOUR); 14 | const minutes = Math.trunc((duration / MINUTE) % 60); 15 | const seconds = Math.trunc(duration % 60); 16 | if (hours === 0) { 17 | if (minutes === 0) { 18 | return `${seconds}s`; 19 | } 20 | return `${minutes}m ${seconds}s`; 21 | } 22 | return `${hours}h ${minutes}m ${seconds}s`; 23 | } 24 | return ''; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/shared/services/content-history.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { collection, collectionData, Firestore, limit, orderBy, query, QueryConstraint } from '@angular/fire/firestore'; 3 | import { traceUntilFirst } from '@angular/fire/performance'; 4 | import { ContentHistory } from '@shared/models/content-history.model'; 5 | import { Observable } from 'rxjs'; 6 | import { map } from 'rxjs/operators'; 7 | 8 | @Injectable({ providedIn: 'root' }) 9 | export class ContentHistoryService { 10 | constructor(private readonly firestore: Firestore) {} 11 | 12 | findAll(spaceId: string, id: string): Observable { 13 | const queryConstrains: QueryConstraint[] = [orderBy('createdAt', 'desc'), limit(30)]; 14 | return collectionData(query(collection(this.firestore, `spaces/${spaceId}/contents/${id}/histories`), ...queryConstrains), { 15 | idField: 'id', 16 | }).pipe( 17 | traceUntilFirst('Firestore:ContentHistory:findAll'), 18 | map(it => it as ContentHistory[]), 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/shared/services/material.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { MaterialIcons } from '@shared/models/material.model'; 4 | import { Observable } from 'rxjs'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class MaterialService { 8 | constructor(private readonly httpClient: HttpClient) {} 9 | 10 | findAllIcons(): Observable { 11 | return this.httpClient.get(`/assets/material-icons.json`); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/app/shared/services/open-api.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Functions, httpsCallableData } from '@angular/fire/functions'; 3 | import { traceUntilFirst } from '@angular/fire/performance'; 4 | import { Observable } from 'rxjs'; 5 | 6 | @Injectable({ providedIn: 'root' }) 7 | export class OpenApiService { 8 | constructor(private readonly functions: Functions) {} 9 | 10 | generate(spaceId: string): Observable { 11 | const openApiGenerate = httpsCallableData<{ spaceId: string }, string>(this.functions, 'openapi-generate'); 12 | return openApiGenerate({ spaceId }).pipe(traceUntilFirst('Functions:OpenApi:generate')); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/app/shared/services/translate.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Functions, httpsCallableData } from '@angular/fire/functions'; 3 | import { traceUntilFirst } from '@angular/fire/performance'; 4 | import { TranslateData } from '@shared/models/translate.model'; 5 | import { Observable } from 'rxjs'; 6 | import { tap } from 'rxjs/operators'; 7 | 8 | @Injectable({ providedIn: 'root' }) 9 | export class TranslateService { 10 | constructor(private readonly functions: Functions) {} 11 | 12 | translate(data: TranslateData): Observable { 13 | const translate = httpsCallableData(this.functions, 'translate'); 14 | return translate(data).pipe(tap(console.log), traceUntilFirst('Functions:Translate:translate')); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/app/shared/services/translation-history.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { collection, collectionData, Firestore, limit, orderBy, query, QueryConstraint } from '@angular/fire/firestore'; 3 | import { traceUntilFirst } from '@angular/fire/performance'; 4 | import { TranslationHistory } from '@shared/models/translation-history.model'; 5 | import { Observable } from 'rxjs'; 6 | import { map } from 'rxjs/operators'; 7 | 8 | @Injectable({ providedIn: 'root' }) 9 | export class TranslationHistoryService { 10 | constructor(private readonly firestore: Firestore) {} 11 | 12 | findAll(spaceId: string): Observable { 13 | const queryConstrains: QueryConstraint[] = [orderBy('createdAt', 'desc'), limit(30)]; 14 | return collectionData(query(collection(this.firestore, `spaces/${spaceId}/translations_history`), ...queryConstrains), { 15 | idField: 'id', 16 | }).pipe( 17 | traceUntilFirst('Firestore:TranslationsHistory:findAll'), 18 | map(it => it as TranslationHistory[]), 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/shared/validators/asset.validator.ts: -------------------------------------------------------------------------------- 1 | import { ValidatorFn, Validators } from '@angular/forms'; 2 | import { CommonValidator } from './common.validator'; 3 | 4 | export class AssetValidator { 5 | public static NAME: ValidatorFn[] = [ 6 | Validators.required, 7 | CommonValidator.noSpaceAround, 8 | Validators.minLength(3), 9 | Validators.maxLength(100), 10 | ]; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/validators/content.validator.ts: -------------------------------------------------------------------------------- 1 | import { ValidatorFn, Validators } from '@angular/forms'; 2 | import { CommonPattern, CommonValidator } from './common.validator'; 3 | 4 | export class ContentValidator { 5 | public static NAME: ValidatorFn[] = [ 6 | Validators.required, 7 | CommonValidator.noSpaceAround, 8 | Validators.minLength(2), 9 | Validators.maxLength(50), 10 | ]; 11 | 12 | public static SLUG: ValidatorFn[] = [ 13 | Validators.required, 14 | CommonValidator.noSpace, 15 | Validators.pattern(CommonPattern.URL_SLUG), 16 | Validators.minLength(2), 17 | Validators.maxLength(50), 18 | ]; 19 | 20 | public static SCHEMA: ValidatorFn[] = [Validators.required]; 21 | } 22 | -------------------------------------------------------------------------------- /src/app/shared/validators/locale.validator.ts: -------------------------------------------------------------------------------- 1 | import { ValidatorFn, Validators } from '@angular/forms'; 2 | import { CommonValidator } from './common.validator'; 3 | 4 | export class LocaleValidator { 5 | public static LOCALE: ValidatorFn[] = [Validators.required, CommonValidator.requireObject]; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/shared/validators/settings.validator.ts: -------------------------------------------------------------------------------- 1 | import { ValidatorFn, Validators } from '@angular/forms'; 2 | import { CommonValidator } from './common.validator'; 3 | 4 | export class SettingsValidator { 5 | public static UI_COLOR: ValidatorFn[] = []; 6 | public static UI_TEXT: ValidatorFn[] = [CommonValidator.noSpaceAround, Validators.maxLength(30)]; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/shared/validators/space.validator.ts: -------------------------------------------------------------------------------- 1 | import { ValidatorFn, Validators } from '@angular/forms'; 2 | import { CommonValidator } from './common.validator'; 3 | 4 | export class SpaceValidator { 5 | public static NAME: ValidatorFn[] = [ 6 | Validators.required, 7 | CommonValidator.noSpaceAround, 8 | Validators.minLength(3), 9 | Validators.maxLength(30), 10 | ]; 11 | 12 | public static ENVIRONMENT_NAME: ValidatorFn[] = [ 13 | Validators.required, 14 | CommonValidator.noSpaceAround, 15 | Validators.minLength(3), 16 | Validators.maxLength(30), 17 | ]; 18 | public static ENVIRONMENT_URL: ValidatorFn[] = [ 19 | Validators.required, 20 | CommonValidator.noSpace, 21 | Validators.minLength(3), 22 | Validators.maxLength(250), 23 | ]; 24 | } 25 | -------------------------------------------------------------------------------- /src/app/shared/validators/token.validator.ts: -------------------------------------------------------------------------------- 1 | import { ValidatorFn, Validators } from '@angular/forms'; 2 | import { CommonValidator } from './common.validator'; 3 | 4 | export class TokenValidator { 5 | public static NAME: ValidatorFn[] = [ 6 | Validators.required, 7 | CommonValidator.noSpaceAround, 8 | Validators.minLength(3), 9 | Validators.maxLength(30), 10 | ]; 11 | } 12 | -------------------------------------------------------------------------------- /src/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/account_circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/cloud_upload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/audio_file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/description.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/file_present.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/folder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/font_download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/icons/video_file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/assets/logo.png -------------------------------------------------------------------------------- /src/environments/env.ts: -------------------------------------------------------------------------------- 1 | export const env = { 2 | LOCALESS_FIREBASE_PROJECT_ID: '', 3 | LOCALESS_FIREBASE_APP_ID: '', 4 | LOCALESS_FIREBASE_STORAGE_BUCKET: '', 5 | LOCALESS_FIREBASE_API_KEY: '', 6 | LOCALESS_FIREBASE_AUTH_DOMAIN: '', 7 | LOCALESS_FIREBASE_MESSAGING_SENDER_ID: '', 8 | LOCALESS_FIREBASE_MEASUREMENT_ID: '', 9 | LOCALESS_AUTH_CUSTOM_DOMAIN: '', 10 | LOCALESS_AUTH_PROVIDERS: '', 11 | LOCALESS_LOGIN_MESSAGE: '', 12 | LOCALESS_UNSPLASH_ENABLE: '', 13 | }; 14 | -------------------------------------------------------------------------------- /src/environments/environment.docker.ts: -------------------------------------------------------------------------------- 1 | 2 | export const environment = { 3 | appName: 'Localess', 4 | firebase: { 5 | projectId: 'demo-localess-dev', 6 | appId: '1:19232484518261:web:47779533df41508d8a706b', 7 | storageBucket: 'demo-localess-dev.appspot.com', 8 | locationId: 'europe-west6', 9 | apiKey: 'AIzaSyAGDhKpaTfxnX7kLeXQiuD-1sBWw0z9b2g', 10 | authDomain: 'demo-localess-dev.firebaseapp.com', 11 | messagingSenderId: '19232484518261', 12 | }, 13 | auth: { 14 | customDomain: '*', 15 | providers: 'GOOGLE,MICROSOFT', 16 | }, 17 | login: { 18 | message: '', 19 | }, 20 | plugins: { 21 | unsplash: false, 22 | }, 23 | production: false, 24 | test: true, 25 | debug: false, 26 | emulator : { 27 | enabled: true, 28 | }, 29 | version: '2.5.1', 30 | }; 31 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | import { env } from './env'; 2 | 3 | export const environment = { 4 | appName: 'Localess', 5 | firebase: { 6 | projectId: env.LOCALESS_FIREBASE_PROJECT_ID, 7 | appId: env.LOCALESS_FIREBASE_APP_ID, 8 | storageBucket: env.LOCALESS_FIREBASE_STORAGE_BUCKET, 9 | apiKey: env.LOCALESS_FIREBASE_API_KEY, 10 | authDomain: env.LOCALESS_FIREBASE_AUTH_DOMAIN, 11 | messagingSenderId: env.LOCALESS_FIREBASE_MESSAGING_SENDER_ID, 12 | measurementId: env.LOCALESS_FIREBASE_MEASUREMENT_ID, 13 | }, 14 | auth: { 15 | customDomain: env.LOCALESS_AUTH_CUSTOM_DOMAIN, 16 | providers: env.LOCALESS_AUTH_PROVIDERS, 17 | }, 18 | login: { 19 | message: env.LOCALESS_LOGIN_MESSAGE, 20 | }, 21 | plugins: { 22 | unsplash: env.LOCALESS_UNSPLASH_ENABLE === 'true', 23 | }, 24 | production: true, 25 | test: false, 26 | debug: false, 27 | emulator : { 28 | enabled: false, 29 | }, 30 | version: '2.5.1', 31 | }; 32 | -------------------------------------------------------------------------------- /src/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/favicon-16x16.png -------------------------------------------------------------------------------- /src/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/favicon-32x32.png -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lessify/localess/7c7aadb6818c4c06b21e044158794805961a549c/src/favicon.ico -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | 3 | import { bootstrapApplication } from '@angular/platform-browser'; 4 | import { environment } from './environments/environment'; 5 | import { AppComponent } from './app/app.component'; 6 | import { appConfig } from './app/app.config'; 7 | 8 | if (environment.production) { 9 | enableProdMode(); 10 | } 11 | 12 | bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /src/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Localess", 3 | "short_name": "Localess", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#FFFFFF", 17 | "background_color": "#FFFFFF", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /src/styles/_background.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | @import './styles-variables'; 4 | 5 | .file-drag-and-drop-wrapper { 6 | background-color: var(--mat-sys-primary-container) !important; 7 | outline: var(--mat-sys-primary) solid 3px !important; 8 | opacity: 0.5; 9 | } 10 | 11 | 12 | //.file-drag-and-drop-wrapper::after { 13 | // content: "Drop it here"; 14 | // position: absolute; 15 | // white-space: pre; 16 | // background-image: url("/assets/cloud_upload.svg"); 17 | // background-position: top; 18 | // background-size: 100px; 19 | // background-repeat: no-repeat; 20 | // inset: 0; 21 | // font-weight: bold; 22 | // text-align: center; 23 | // font-size: 30px; 24 | // top: 30vh; 25 | // //animation: bounce 2s ease infinite; 26 | //} 27 | 28 | @keyframes bounce { 29 | 0%, 20%, 50%, 80%, 100% {transform: translateY(0);} 30 | 40% {transform: translateY(-10px);} 31 | 60% {transform: translateY(-5px);} 32 | } 33 | -------------------------------------------------------------------------------- /src/styles/_layout.scss: -------------------------------------------------------------------------------- 1 | .container-full-screen { 2 | @apply px-2 mx-auto mt-3 3 | } 4 | 5 | .full-screen { 6 | @apply mx-auto 7 | } 8 | -------------------------------------------------------------------------------- /src/styles/_markdown.scss: -------------------------------------------------------------------------------- 1 | markdown { 2 | blockquote { 3 | border-left: 3px solid rgba(0, 0, 0, 0.21); 4 | padding-left: 12px; 5 | color: rgba(0, 0, 0, 0.54); 6 | } 7 | 8 | ol, ul { 9 | margin: revert; 10 | padding: revert; 11 | } 12 | ul { 13 | list-style: revert; 14 | } 15 | ol { 16 | list-style: revert; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/styles/_mat-card.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | @import './styles-variables'; 4 | 5 | mat-card { 6 | &.ll-not-shadow { 7 | box-shadow: none; 8 | background-color: transparent; 9 | } 10 | &.invalid { 11 | border: solid 2px var(--mat-sys-error); 12 | } 13 | &.digital-asset-card { 14 | max-width: 240px; 15 | min-width: 240px; 16 | img { 17 | min-width: 240px; 18 | min-height: 240px; 19 | max-width: 240px; 20 | max-height: 240px; 21 | border-top-left-radius: inherit; 22 | border-top-right-radius: inherit; 23 | border-bottom-width: var(--mdc-outlined-card-outline-width); 24 | border-bottom-color: var(--mdc-outlined-card-outline-color, var(--mat-app-outline-variant)); 25 | } 26 | .progress { 27 | min-width: 240px; 28 | min-height: 240px; 29 | max-width: 240px; 30 | max-height: 240px; 31 | align-content: center; 32 | padding-left: 60px; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/styles/_mat-grid-list.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | @import './styles-variables'; 4 | 5 | mat-grid-list { 6 | &.start { 7 | .mat-grid-tile .mat-grid-tile-content { 8 | justify-content: flex-start !important; 9 | align-items: flex-start !important; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/styles/_mat-menu.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | @import './styles-variables'; 4 | 5 | .mat-menu-error-messages { 6 | max-width: 500px !important; 7 | } 8 | -------------------------------------------------------------------------------- /src/styles/_mat-paginator.scss: -------------------------------------------------------------------------------- 1 | mat-paginator { 2 | &.mat-paginator-sticky { 3 | @apply sticky bottom-0 z-10; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/styles/_mat-snack-bar.scss: -------------------------------------------------------------------------------- 1 | // Notifications 2 | mat-snack-bar-container { 3 | &.error-notification-overlay { 4 | .mdc-snackbar__surface { 5 | color: var(--mat-sys-on-error-container); 6 | background-color: var(--mat-sys-error-container); 7 | } 8 | } 9 | &.success-notification-overlay { 10 | .mdc-snackbar__surface { 11 | color: var(--mat-sys-on-primary-container); 12 | background-color: var(--mat-sys-primary-container); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/styles/_mat-table.scss: -------------------------------------------------------------------------------- 1 | mat-table { 2 | mat-row { 3 | &:hover { 4 | background: rgba(0, 0, 0, 0.04); 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/styles/_mat-toolbar.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | 3 | mat-toolbar-row { 4 | .actions { 5 | @apply flex gap-2 items-center; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; 6 | 7 | // First, initialize the Angular testing environment. 8 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 9 | -------------------------------------------------------------------------------- /storage.rules: -------------------------------------------------------------------------------- 1 | rules_version = '2'; 2 | service firebase.storage { 3 | match /b/{bucket}/o { 4 | match /{allPaths=**} { 5 | allow read: if request.auth!=null; 6 | allow write: if request.auth!=null; 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": ["src/main.ts", "src/polyfills.ts"], 9 | "exclude": ["functions"], 10 | "include": ["src/**/*.d.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.script.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "noImplicitReturns": true, 6 | "noUnusedLocals": true, 7 | "outDir": "./src/scripts", 8 | "sourceMap": false, 9 | "strict": true, 10 | "target": "ES2020", 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true 13 | }, 14 | "compileOnSave": true, 15 | "include": ["scripts/sync-v1.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": ["jasmine"] 7 | }, 8 | "files": ["src/test.ts", "src/polyfills.ts"], 9 | "exclude": ["functions"], 10 | "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] 11 | } 12 | --------------------------------------------------------------------------------