├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── instructions │ └── copilot-instructions.md ├── .gitignore ├── .vite └── deps │ ├── _metadata.json │ └── package.json ├── .vscode └── settings.json ├── AzureMapsGrid ├── .eslintrc.json ├── .gitignore ├── AzureMapsGrid.pcfproj ├── AzureMapsGrid │ ├── AzureMapsGridControl.tsx │ ├── AzureMapsGridControl │ │ ├── .gitignore │ │ ├── AzureMapsGridControl.cdsproj │ │ ├── Controls │ │ │ └── raw_RAW.AzureMapsGrid.AzureMapsGrid │ │ │ │ ├── ControlManifest.xml │ │ │ │ ├── ControlManifest.xml.data.xml │ │ │ │ ├── bundle.js │ │ │ │ └── css │ │ │ │ └── AzureMapsGrid.css │ │ ├── Entities │ │ │ └── raw_azuremapsconfig │ │ │ │ ├── Entity.xml │ │ │ │ ├── FormXml │ │ │ │ ├── card │ │ │ │ │ ├── {419de572-8678-4625-a9bc-a9a5ad1fbb42}.xml │ │ │ │ │ └── {419de572-8678-4625-a9bc-a9a5ad1fbb42}_managed.xml │ │ │ │ ├── main │ │ │ │ │ ├── {8f94d5d3-31e0-40d7-b3e3-55f9d5b9c38c}.xml │ │ │ │ │ └── {8f94d5d3-31e0-40d7-b3e3-55f9d5b9c38c}_managed.xml │ │ │ │ └── quick │ │ │ │ │ ├── {1d791903-0181-4e65-b9de-981a2e3ed1ed}.xml │ │ │ │ │ └── {1d791903-0181-4e65-b9de-981a2e3ed1ed}_managed.xml │ │ │ │ ├── RibbonDiff.xml │ │ │ │ └── SavedQueries │ │ │ │ ├── {1eab5070-7af9-4a9f-8a46-6a2628998602}.xml │ │ │ │ ├── {2d385366-63f4-4440-b51b-72a8f88cc502}.xml │ │ │ │ ├── {40ff0baa-7642-484e-a6f4-f329d7c793c9}.xml │ │ │ │ ├── {4a465148-14ae-43ea-adbe-d17b6a60bab1}.xml │ │ │ │ ├── {6072346f-91ab-4b51-89ba-88c22c3a4425}.xml │ │ │ │ ├── {cee6f7fa-e25f-ea11-a811-000d3a59f6ff}.xml │ │ │ │ └── {e3214bf5-cfed-4001-9ed5-08b037e31505}.xml │ │ ├── OptionSets │ │ │ └── raw_azuremapsauthenticationtype.xml │ │ ├── Other │ │ │ ├── Customizations.xml │ │ │ ├── Relationships.xml │ │ │ ├── Relationships │ │ │ │ ├── BusinessUnit.xml │ │ │ │ ├── Owner.xml │ │ │ │ ├── SystemUser.xml │ │ │ │ └── Team.xml │ │ │ └── Solution.xml │ │ └── Workflows │ │ │ ├── AuthenticationTypeChanges-8B852C0C-E85F-EA11-A811-000D3A59F6FF.xaml │ │ │ ├── AuthenticationTypeChanges-8B852C0C-E85F-EA11-A811-000D3A59F6FF.xaml.data.xml │ │ │ ├── SetNameFieldToPreventDuplicate-5876FC0E-5469-EA11-A811-000D3A59F6FF.xaml │ │ │ └── SetNameFieldToPreventDuplicate-5876FC0E-5469-EA11-A811-000D3A59F6FF.xaml.data.xml │ ├── ControlManifest.Input.xml │ ├── css │ │ └── AzureMapsGrid.css │ ├── index.ts │ └── preview.png ├── README.md ├── featureconfig.json ├── package-lock.json ├── package.json ├── pcfconfig.json ├── spkl.json ├── tsconfig.json └── unpack.ps1 ├── BingMapsGrid ├── .eslintrc.json ├── .gitignore ├── BingMapsGrid.pcfproj ├── BingMapsGrid │ ├── BingMapsGridControl │ │ ├── .gitignore │ │ ├── BingMapsGridControl.cdsproj │ │ └── Other │ │ │ ├── Customizations.xml │ │ │ ├── Relationships.xml │ │ │ └── Solution.xml │ ├── ControlManifest.Input.xml │ ├── css │ │ └── BingMapsGrid.css │ ├── index.ts │ └── preview.png ├── README.md ├── featureconfig.json ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── BooleanOptionset ├── .eslintrc.json ├── .gitignore ├── BooleanOptionset.pcfproj ├── BooleanOptionset │ ├── BooleanOptionsetControl │ │ ├── .gitignore │ │ ├── BooleanOptionsetControl.cdsproj │ │ └── Other │ │ │ ├── Customizations.xml │ │ │ ├── Relationships.xml │ │ │ └── Solution.xml │ ├── ControlManifest.Input.xml │ ├── css │ │ └── style.css │ └── index.ts ├── README.md ├── featureconfig.json ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── Calendar ├── .eslintrc.json ├── .gitignore ├── Calendar.pcfproj ├── Calendar │ ├── CalendarControl.tsx │ ├── CalendarControl │ │ ├── .gitignore │ │ ├── CalendarControl.cdsproj │ │ └── Other │ │ │ ├── Customizations.xml │ │ │ ├── Relationships.xml │ │ │ └── Solution.xml │ ├── ControlManifest.Input.xml │ ├── accessors │ │ └── tooltipAccessor.tsx │ ├── components │ │ ├── MobileToolbar.tsx │ │ ├── Translations.tsx │ │ └── WorkWeek.tsx │ ├── css │ │ └── react-big-calendar.override.css │ ├── getters │ │ ├── dayPropsGetter.ts │ │ ├── eventPropsGetter.ts │ │ └── index.ts │ ├── handlers │ │ ├── handleEventKeyPress.ts │ │ ├── handleEventSelected.ts │ │ ├── handleNavigate.ts │ │ ├── handleOnView.ts │ │ ├── handleSlotSelect.ts │ │ └── index.ts │ ├── hooks │ │ ├── index.ts │ │ ├── useCalendarColors.ts │ │ ├── useCalendarData.ts │ │ ├── useCalendarDate.ts │ │ ├── useCalendarHourRange.ts │ │ ├── useCalendarPopup.ts │ │ ├── useCalendarSelectable.ts │ │ ├── useCalendarStepAndTimeslots.ts │ │ ├── useCalendarView.ts │ │ ├── useDayLayoutAlgorithm.ts │ │ ├── useEventHeaderFormat.ts │ │ └── useEventSelectable.ts │ ├── index.ts │ ├── renderers │ │ ├── agendaEventRenderer.tsx │ │ ├── index.ts │ │ ├── resourceHeaderRenderer.tsx │ │ ├── timeGutterHeaderRenderer.tsx │ │ └── timeSlotWrapperRenderer.tsx │ ├── types │ │ ├── IEvent.ts │ │ ├── Keys.ts │ │ ├── Resource.ts │ │ ├── SlotInfo.ts │ │ ├── index.ts │ │ ├── is-hexcolor.d.ts │ │ └── react-big-calendar.d.ts │ └── utils │ │ ├── CalendarHelpers.ts │ │ ├── Constants.ts │ │ ├── DataHelpers.ts │ │ └── index.ts ├── README.md ├── Sample │ ├── CanvasCalendar_1.0.0.5.zip │ ├── CanvasCalendar_1.0.0.5_managed.zip │ ├── CanvasCalendar_1_0_0_4.zip │ └── CanvasCalendar_1_0_0_4_managed.zip ├── featureconfig.json ├── images │ ├── CalendarControlForCanvasAndModel.png │ ├── CanvasCalendarAllResourcesAdvancedProps.png │ ├── CanvasCalendarAllResourcesDataSource.png │ ├── CanvasCalendarAllResourcesResourceHeader.png │ ├── CanvasCalendarDateControlProp.png │ ├── CanvasCalendarDateOnChange.png │ ├── CanvasCalendarDateOnStart.png │ ├── CanvasCalendarDatePickerProps.png │ ├── CanvasCalendarEventsOnly.png │ ├── CanvasCalendarEventsOnlyAdvancedProps.png │ ├── CanvasCalendarEventsOnlyDataSource.png │ ├── CanvasCalendarEventsOnlyOnLoad.png │ ├── CanvasCalendarOnChange.png │ ├── CanvasCalendarOnChangeProperties.png │ ├── CanvasCalendarResourcesWithEventsAdvancedProps.png │ ├── CanvasCalendarResourcesWithEventsData.png │ ├── CanvasCalendarResourcesWithEventsDataSource.png │ ├── CanvasCalendarResourcesWithEventsResourceHeader.png │ ├── ModelCalendarAddColumns.png │ ├── ModelCalendarAddControl.png │ ├── ModelCalendarSelectCalendarControl.png │ ├── ModelCalendarSelectProperties.png │ ├── ModelCalendarShowAs.png │ ├── ModelCalendarShowAsCalendar.png │ ├── ModelCalendarSubGrid.png │ ├── ModelCalendarSubGridHeight.png │ └── calendarcontrol.gif ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── CanvasFileDownloader ├── .eslintrc.json ├── .gitignore ├── CanvasFileDownloader.pcfproj ├── CanvasFileDownloader │ ├── ControlManifest.Input.xml │ └── index.ts ├── README.md ├── Solution │ └── CanvasFileDownloaderControl │ │ ├── .gitignore │ │ ├── CanvasFileDownloaderControl.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── featureconfig.json ├── images │ ├── AddComponentToForm.png │ ├── CanvasFileDownloader.png │ ├── ComponentProperties.png │ ├── DownloadButton.png │ ├── FileDownloaded.png │ ├── ImportComponent.png │ └── ImportComponentRibbon.png ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── CanvasFileUploader ├── .eslintrc.json ├── .gitignore ├── CanvasFileUploader.pcfproj ├── CanvasFileUploader │ ├── ControlManifest.Input.xml │ └── index.ts ├── README.md ├── Solution │ └── CanvasFileUploaderComponent │ │ ├── .gitignore │ │ ├── CanvasFileUploaderComponent.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── featureconfig.json ├── images │ ├── AddComponentToForm.png │ ├── CanvasComponentUpload.png │ ├── CanvasFileUploader.gif │ ├── ComponentProperties.png │ ├── CustomAppStart.png │ ├── ImageViewer.png │ ├── ImportComponent.png │ ├── ImportComponentRibbon.png │ ├── PDFViewer.png │ └── StandardInput.png ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── ColorPicker ├── .eslintrc.json ├── .gitignore ├── ColorPicker.pcfproj ├── ColorPicker │ ├── ColorPicker.tsx │ ├── ControlManifest.Input.xml │ ├── ControlPicker │ │ ├── .gitignore │ │ ├── ControlPicker.cdsproj │ │ └── Other │ │ │ ├── Customizations.xml │ │ │ ├── Relationships.xml │ │ │ └── Solution.xml │ ├── index.ts │ └── preview.png ├── README.md ├── featureconfig.json ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── DadJoke ├── .eslintrc.json ├── .gitignore ├── DadJoke.pcfproj ├── DadJoke │ ├── ControlManifest.Input.xml │ ├── css │ │ └── DadJoke.css │ ├── img │ │ └── preview.png │ ├── index.ts │ └── strings │ │ └── DadJoke.1033.resx ├── Solution │ └── RAW!DadJoke │ │ ├── .gitignore │ │ ├── RAW!DadJoke.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── DetailListGrid ├── .eslintrc.json ├── .gitignore ├── DetailListGrid.pcfproj ├── DetailListGrid │ ├── ControlManifest.Input.xml │ ├── DetailListGridControl.tsx │ ├── DetailListGridControl │ │ ├── .gitignore │ │ ├── DetailListGridControl.cdsproj │ │ └── Other │ │ │ ├── Customizations.xml │ │ │ ├── Relationships.xml │ │ │ └── Solution.xml │ ├── css │ │ └── DetailListGridControl.css │ └── index.ts ├── README.md ├── featureconfig.json ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── DocxTemplatesCanvas ├── .eslintrc.json ├── .gitignore ├── DocxTemplatesCanvas.pcfproj ├── DocxTemplatesCanvas │ ├── ControlManifest.Input.xml │ └── index.ts ├── README.MD ├── Sample │ ├── DocxTemplateSample_1_0_0_1.zip │ ├── DocxTemplateSample_1_0_0_1_managed.zip │ ├── SampleTemplate.docx │ ├── SampleTemplate.png │ └── contoso.png ├── Solution │ └── RAWDocxTemplatesCanvas │ │ ├── .gitignore │ │ ├── RAWDocxTemplatesCanvas.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── featureconfig.json ├── image.png ├── package-lock.json ├── package.json ├── pcfconfig.json ├── tsconfig.json └── webpack.config.js ├── DownloadTools.ps1 ├── ExportPDFManager ├── .gitignore ├── ExportPDFManager.pcfproj ├── ExportPDFManager │ ├── ControlManifest.Input.xml │ ├── ExportPDFManagerApp.tsx │ ├── components │ │ └── ExportPDFManager.tsx │ ├── hooks │ │ └── useDisabledStatus.ts │ ├── index.ts │ ├── resources │ │ ├── ExportPDFManager.1025.resx │ │ ├── ExportPDFManager.1031.resx │ │ ├── ExportPDFManager.1033.resx │ │ ├── ExportPDFManager.1036.resx │ │ ├── ExportPDFManager.1040.resx │ │ ├── ExportPDFManager.1041.resx │ │ ├── ExportPDFManager.1042.resx │ │ ├── ExportPDFManager.1043.resx │ │ ├── ExportPDFManager.3082.resx │ │ └── ExportPDFManager.ts │ ├── services │ │ ├── MetadataService.ts │ │ ├── PcfContext.tsx │ │ └── PcfContextService.ts │ ├── types │ │ ├── PdfEntity.ts │ │ ├── PdfSetting.ts │ │ ├── SaveState.ts │ │ └── index.ts │ └── utils │ │ └── styles.ts ├── README.MD ├── Solution │ └── ExportPDFManagerControl │ │ ├── .gitignore │ │ ├── ExportPDFManagerControl.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── eslint.config.mjs ├── featureconfig.json ├── images │ ├── 2025-03-31_16-12-42.PNG │ ├── 2025-03-31_16-13-13.PNG │ ├── 2025-04-02_15-21-37.PNG │ ├── 2025-04-02_15-22-37.PNG │ └── Export PDF Manager.gif ├── package-lock.json ├── package.json ├── pcfconfig.json ├── tsconfig.json └── webpack.config.js ├── Frame ├── .eslintrc.json ├── .gitignore ├── RAWframeComponent.pcfproj ├── README.md ├── Sample │ └── RAWFrameSample_1_0_0_5_managed.zip ├── Solution │ └── RAWframe │ │ ├── .gitignore │ │ ├── RAWframe.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── featureconfig.json ├── frame │ ├── ControlManifest.Input.xml │ └── index.ts ├── images │ └── RAWFrame.png ├── js │ ├── BackButton.html │ ├── CanvasAppLauncher.html │ ├── CreateContacts.html │ ├── DefaultOptionSetDisplayValue.html │ └── GetFirstAccount.html ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── LICENSE ├── PDFFormFillCanvas ├── .eslintrc.json ├── .gitignore ├── PDFFormFillCanvas.pcfproj ├── PDFFormFillCanvas │ ├── ControlManifest.Input.xml │ └── index.ts ├── README.md ├── Sample │ └── PDFFormFiller_1_0_0_1_managed.zip ├── Solutions │ └── RAWPDFFormFillCanvas │ │ ├── .gitignore │ │ ├── RAWPDFFormFillCanvas.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── featureconfig.json ├── images │ ├── ImportComponent.png │ ├── ImportComponentFromCode.png │ ├── PDFFormFill.png │ └── YouTube.png ├── package-lock.json ├── package.json ├── pcfconfig.json ├── tsconfig.json └── webpack.config.js ├── PowerPagesFileManager ├── .gitignore ├── PowerPagesFileManager.pcfproj ├── PowerPagesFileManager │ ├── ControlManifest.Input.xml │ ├── PortalFilesApp.tsx │ ├── components │ │ ├── AnnotationsGrid.tsx │ │ ├── DeleteConfirmationDialog.tsx │ │ ├── FileOverwriteDialog.tsx │ │ └── HeaderButtons.tsx │ ├── hooks │ │ ├── useAnnotations.ts │ │ ├── useFileUploads.ts │ │ └── useWindowSize.ts │ ├── index.ts │ ├── resources │ │ ├── PortalFiles.1031.resx │ │ ├── PortalFiles.1033.resx │ │ ├── PortalFiles.1034.resx │ │ ├── PortalFiles.1036.resx │ │ ├── PortalFiles.1040.resx │ │ ├── PortalFiles.1041.resx │ │ ├── PortalFiles.1042.resx │ │ ├── PortalFiles.1043.resx │ │ ├── PortalFiles.1046.resx │ │ ├── PortalFiles.2052.resx │ │ └── PortalFiles.3082.resx │ ├── services │ │ ├── AnnotationService.ts │ │ ├── HttpClient.ts │ │ ├── PcfContext.tsx │ │ └── PcfContextService.ts │ ├── types │ │ ├── Annotations.ts │ │ └── index.ts │ └── utils │ │ ├── constants.ts │ │ ├── formatDate.ts │ │ ├── index.ts │ │ ├── layouts.ts │ │ ├── localization.ts │ │ └── themeGenerator.ts ├── README.MD ├── Solution │ └── PowerPagesFileManagerSolution │ │ ├── .gitignore │ │ ├── PowerPagesFileManagerSolution.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── eslint.config.mjs ├── images │ └── PowerPagesFileManager.gif ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── README.md ├── RestrictedChoice ├── .gitignore ├── README.MD ├── RestrictedChoice.pcfproj ├── RestrictedChoice │ ├── ControlManifest.Input.xml │ ├── RestrictedChoiceApp.tsx │ ├── components │ │ └── RestrictedChoice.tsx │ ├── index.ts │ ├── resources │ │ ├── RestrictedChoice.1025.resx │ │ ├── RestrictedChoice.1031.resx │ │ ├── RestrictedChoice.1033.resx │ │ ├── RestrictedChoice.1036.resx │ │ ├── RestrictedChoice.1040.resx │ │ ├── RestrictedChoice.1041.resx │ │ ├── RestrictedChoice.1042.resx │ │ ├── RestrictedChoice.1043.resx │ │ └── RestrictedChoice.3082.resx │ ├── services │ │ ├── PcfContext.tsx │ │ └── PcfContextService.ts │ └── utils │ │ └── styles.ts ├── Solution │ └── RestrictedChoiceControl │ │ ├── .gitignore │ │ ├── RestrictedChoiceControl.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── eslint.config.mjs ├── featureconfig.json ├── images │ └── 2025-03-07_15-36-00.png ├── package-lock.json ├── package.json ├── pcfconfig.json ├── tsconfig.json └── webpack.config.js ├── RotationalImage ├── .eslintrc.json ├── .gitignore ├── README.md ├── RotationalImage.pcfproj ├── RotationalImage │ ├── ControlManifest.Input.xml │ ├── RotationalImageComponent.tsx │ └── index.ts ├── Solution │ └── RotationalImageComponent │ │ ├── .gitignore │ │ ├── RotationalImageComponent.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── featureconfig.json ├── images │ ├── AddComponentToForm.png │ ├── ComponentProperties.png │ ├── ConverImageToBase64.gif │ ├── ImportComponent.png │ ├── ImportComponentRibbon.png │ ├── RotationalImage.gif │ └── RunOnStart.png ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── RuntimeInfo ├── .eslintrc.json ├── .gitignore ├── README.md ├── RuntimeInfo.pcfproj ├── RuntimeInfo │ ├── ControlManifest.Input.xml │ ├── browser-info.d.ts │ └── index.ts ├── Solution │ └── RuntimeInfoComponent │ │ ├── .gitignore │ │ ├── RuntimeInfoComponent.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── featureconfig.json ├── images │ ├── EditComponentName.png │ ├── EditComponentNameUpdateName.png │ ├── ImportComponent.png │ ├── ImportComponentFromCode.png │ ├── RunTimeInfo.png │ ├── RuntimeInfoDesktopFirefox.png │ ├── RuntimeInfoPhone.png │ └── UtilizePropertyInTextField.png ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── Scheduler ├── .github │ └── instructions │ │ └── copilot.instructions.md ├── .gitignore ├── .vscode │ └── settings.json ├── README.md ├── Sample │ └── RAW! Scheduler Sample.msapp ├── Scheduler.pcfproj ├── Scheduler │ ├── ControlManifest.Input.xml │ ├── components │ │ ├── callbacks │ │ │ ├── eventClicked.ts │ │ │ ├── index.ts │ │ │ ├── newEvent.ts │ │ │ ├── nextClick.ts │ │ │ ├── onViewChange.ts │ │ │ ├── prevClick.ts │ │ │ ├── slotClickedFunc.ts │ │ │ └── toggleExpandFunc.ts │ │ ├── renderers │ │ │ ├── eventItemPopoverTemplateResolver.tsx │ │ │ ├── eventItemTemplateResolver.tsx │ │ │ └── index.ts │ │ ├── scheduler.tsx │ │ └── schedulerWrapper.tsx │ ├── hooks │ │ ├── index.ts │ │ ├── useAvailableViews.ts │ │ ├── useDayViewOptions.ts │ │ ├── useDisplayWeekend.ts │ │ ├── useNonWorkingTimeColors.ts │ │ ├── useResourceNameHeader.ts │ │ ├── useSchedulerDate.ts │ │ ├── useSchedulerLanguage.ts │ │ ├── useSchedulerView.ts │ │ ├── useShowHeader.ts │ │ └── useWorkWeekDays.ts │ ├── index.ts │ ├── mocks │ │ ├── MockPCFClient.ts │ │ ├── MockPCFContext.ts │ │ ├── MockPCFDataSet.ts │ │ ├── MockPCFDevice.ts │ │ ├── MockPCFFactory.ts │ │ ├── MockPCFFormatting.ts │ │ ├── MockPCFMode.ts │ │ ├── MockPCFNavigation.ts │ │ ├── MockPCFParameters.ts │ │ ├── MockPCFResources.ts │ │ ├── MockPCFUserSettings.ts │ │ ├── MockPCFUtility.ts │ │ ├── MockPCFWebApi.ts │ │ └── index.ts │ ├── resources │ │ └── schedulerOverrides.css │ ├── schedulerApp.tsx │ ├── services │ │ ├── calendarDataService.ts │ │ ├── metadataService.ts │ │ ├── pcfContext.tsx │ │ ├── pcfContextService.ts │ │ └── schedulerBehaviors.ts │ ├── test │ │ ├── index.html │ │ ├── main.tsx │ │ ├── testApp.tsx │ │ ├── tsconfig.app.json │ │ └── vite.config.ts │ ├── types │ │ ├── extendedSchedulerData.ts │ │ ├── index.ts │ │ ├── schedulerTypes.ts │ │ └── schedulerViews.ts │ └── utils │ │ ├── constants.ts │ │ ├── demoData.ts │ │ ├── formattingHelpers.ts │ │ ├── locales.ts │ │ └── localization.ts ├── Solution │ └── RAWSchedulerComponent │ │ ├── .gitignore │ │ ├── RAWSchedulerComponent.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── eslint.config.mjs ├── featureconfig.json ├── images │ └── scheduler-demo.gif ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── WorldDaylightMap ├── .eslintrc.json ├── .gitignore ├── README.md ├── Sample │ └── World Daylight Map.msapp ├── Solution │ └── RAWWorldDaylightMap │ │ ├── .gitignore │ │ ├── RAWWorldDaylightMap.cdsproj │ │ └── src │ │ └── Other │ │ ├── Customizations.xml │ │ ├── Relationships.xml │ │ └── Solution.xml ├── WorldDaylightMap.pcfproj ├── WorldDaylightMap │ ├── ControlManifest.Input.xml │ ├── WorldDaylightMap.tsx │ ├── css │ │ └── WorldDaylightMap.css │ ├── img │ │ └── preview.png │ ├── index.ts │ └── strings │ │ └── WorldDaylightMap.1033.resx ├── featureconfig.json ├── images │ └── world-daylight-map.png ├── package-lock.json ├── package.json ├── pcfconfig.json └── tsconfig.json ├── azure-pipelines.yml ├── package-lock.json └── package.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] [PCF Component Name] Issue" 5 | labels: '' 6 | assignees: rwilson504 7 | 8 | --- 9 | 10 | **Which PCF Component** 11 | Which PCF component is this bug related to: Azure Maps Grid, Calendar, Canvas File Uploader, etc... 12 | 13 | **What type of Power App are you using this PCF component in?** 14 | - Model App 15 | - Custom Page inside Model App 16 | - Canvas App 17 | - Portal/Pages 18 | 19 | **Describe the bug** 20 | A clear and concise description of what the bug is. 21 | 22 | **To Reproduce** 23 | Steps to reproduce the behavior: 24 | 1. Go to '...' 25 | 2. Click on '....' 26 | 3. Scroll down to '....' 27 | 4. See error 28 | 29 | **Expected behavior** 30 | A clear and concise description of what you expected to happen. 31 | 32 | **Screenshots** 33 | If applicable, add screenshots to help explain your problem. 34 | 35 | **Additional context** 36 | Add any other context about the problem here. 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE] [PCF Component Name] Feature" 5 | labels: '' 6 | assignees: rwilson504 7 | 8 | --- 9 | 10 | **Which PCF Component** 11 | Which PCF component is this feature request related to: Azure Maps Grid, Calendar, Canvas File Uploader, etc... 12 | 13 | **Is your feature request related to a problem? Please describe.** 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | **Describe the solution you'd like** 17 | A clear and concise description of what you want to happen. 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj 15 | 16 | /Tools 17 | /temp 18 | 19 | log*.txt -------------------------------------------------------------------------------- /.vite/deps/_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "hash": "74cfacbe", 3 | "configHash": "56cbeece", 4 | "lockfileHash": "e3b0c442", 5 | "browserHash": "ac57c1d0", 6 | "optimized": {}, 7 | "chunks": {} 8 | } -------------------------------------------------------------------------------- /.vite/deps/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "github.copilot.chat.codeGeneration.useInstructionFiles": true, 3 | "chat.instructionsFilesLocations": { 4 | ".github": true 5 | }, 6 | } -------------------------------------------------------------------------------- /AzureMapsGrid/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off", 25 | "@typescript-eslint/no-empty-object-type": "off" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /AzureMapsGrid/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Controls/raw_RAW.AzureMapsGrid.AzureMapsGrid/ControlManifest.xml.data.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | raw_RAW.AzureMapsGrid.AzureMapsGrid 4 | /Controls/raw_RAW.AzureMapsGrid.AzureMapsGrid/ControlManifest.xml 5 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Entities/raw_azuremapsconfig/RibbonDiff.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Entities/raw_azuremapsconfig/SavedQueries/{cee6f7fa-e25f-ea11-a811-000d3a59f6ff}.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 1 5 | 1 6 | 0 7 | 0 8 | 1 9 | {cee6f7fa-e25f-ea11-a811-000d3a59f6ff} 10 | 8192 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 1.0.0.0 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/OptionSets/raw_azuremapsauthenticationtype.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | picklist 4 | 1 5 | 1.0.0.0 6 | 1 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 31 | 39 | 40 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 1033 16 | 17 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Other/Relationships/BusinessUnit.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | OneToMany 5 | 1 6 | 1.0.0.0 7 | 0 8 | raw_azuremapsconfig 9 | BusinessUnit 10 | NoCascade 11 | NoCascade 12 | NoCascade 13 | NoCascade 14 | NoCascade 15 | OwningBusinessUnit 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Other/Relationships/Owner.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | OneToMany 5 | 1 6 | 1.0.0.0 7 | 0 8 | raw_azuremapsconfig 9 | Owner 10 | NoCascade 11 | NoCascade 12 | NoCascade 13 | NoCascade 14 | NoCascade 15 | OwnerId 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Other/Relationships/Team.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | OneToMany 5 | 1 6 | 1.0.0.0 7 | 0 8 | raw_azuremapsconfig 9 | Team 10 | NoCascade 11 | NoCascade 12 | NoCascade 13 | NoCascade 14 | NoCascade 15 | OwningTeam 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/AzureMapsGridControl/Workflows/AuthenticationTypeChanges-8B852C0C-E85F-EA11-A811-000D3A59F6FF.xaml.data.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | /Workflows/AuthenticationTypeChanges-8B852C0C-E85F-EA11-A811-000D3A59F6FF.xaml 4 | 1 5 | 0 6 | 2 7 | 1 8 | 4 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 1 15 | 2 16 | 1 17 | 1 18 | 1.0.0.0 19 | 1 20 | 0 21 | 1 22 | 1 23 | raw_azuremapsconfig 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /AzureMapsGrid/AzureMapsGrid/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/AzureMapsGrid/AzureMapsGrid/preview.png -------------------------------------------------------------------------------- /AzureMapsGrid/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /AzureMapsGrid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "rebuild": "pcf-scripts rebuild", 9 | "start": "pcf-scripts start" 10 | }, 11 | "dependencies": { 12 | "@types/node": "^10.17.24", 13 | "@types/powerapps-component-framework": "^1.3", 14 | "azure-maps-control": "^2.0.25", 15 | "office-ui-fabric-react": "^7.117.4", 16 | "react": "^16.13.1", 17 | "react-azure-maps": "0.0.6", 18 | "spin.js": "^4.1.0" 19 | }, 20 | "devDependencies": { 21 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 22 | "@typescript-eslint/eslint-plugin": "^8.18.0", 23 | "@typescript-eslint/parser": "^8.18.0", 24 | "eslint": "^8.57.0", 25 | "eslint-plugin-import": "^2.31.0", 26 | "eslint-plugin-node": "^11.1.0", 27 | "eslint-plugin-promise": "^7.1.0", 28 | "pcf-scripts": "^1", 29 | "pcf-start": "^1", 30 | "typescript": "^4.9.5" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /AzureMapsGrid/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /AzureMapsGrid/spkl.json: -------------------------------------------------------------------------------- 1 | { 2 | "solutions": [ 3 | { 4 | "profile": "default,debug", 5 | "solution_uniquename": "AzureMapsGridControl", 6 | "packagepath": ".\\AzureMapsGrid\\AzureMapsGridControl", 7 | "solutionpath": "..\\Output\\AzureMapsGridControl_{0}.{1}.{2}.{3}.zip", 8 | "packagetype": "both_unmanaged_import", 9 | "increment_on_import": false, 10 | "allowdelete": false, 11 | "clobber": false 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /AzureMapsGrid/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /AzureMapsGrid/unpack.ps1: -------------------------------------------------------------------------------- 1 | # ## Create a copy of the original files in the Other Folder. 2 | # if (-Not (Test-Path "$PSScriptRoot\temp")) 3 | # { 4 | # md .\temp\Other 5 | # } 6 | # copy .\AzureMapsGrid\AzureMapsGridControl\*.* .\temp -Force 7 | # copy .\AzureMapsGrid\AzureMapsGridControl\Other\*.* .\temp\Other -Force 8 | 9 | ## Unpack the solution from the server 10 | # $solutionPackager = (Get-ChildItem ..\Tools -Include SolutionPackager.exe -Recurse | Sort-Object FullName -Descending | Select -First 1).FullName 11 | # write-host "Using" $solutionPackager 12 | # &$solutionPackager /action:Extract /zipFile:"AzureMapsGridControl" /folder:".\\AzureMapsGrid\\AzureMapsGridControl" /nologo /log:packagerlog.txt /allowDelete:No /allowWrite:Yes /packagetype:Both 13 | 14 | $spkl = (Get-ChildItem ..\Tools -Include spkl.exe -Recurse | Sort-Object FullName -Descending | Select -First 1).FullName 15 | write-host "Using" $spkl 16 | &$spkl unpack spkl.json $args 17 | 18 | ## Put back the original solution and customization xml files or the pac will not build correctly. 19 | # copy .\temp\*.* .\AzureMapsGrid\AzureMapsGridControl 20 | # copy .\temp\Other\Customizations.xml .\AzureMapsGrid\AzureMapsGridControl\Other -Force 21 | # copy .\temp\Other\Solution.xml .\AzureMapsGrid\AzureMapsGridControl\Other -Force 22 | #Remove-Item .\temp -Force -Recurse -------------------------------------------------------------------------------- /BingMapsGrid/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /BingMapsGrid/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /BingMapsGrid/BingMapsGrid/BingMapsGridControl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /BingMapsGrid/BingMapsGrid/BingMapsGridControl/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /BingMapsGrid/BingMapsGrid/BingMapsGridControl/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /BingMapsGrid/BingMapsGrid/css/BingMapsGrid.css: -------------------------------------------------------------------------------- 1 | #mainDiv { 2 | height: 100%; 3 | } 4 | 5 | #mapDiv { 6 | position:relative; 7 | width:100%; 8 | /* height:calc(100% - 25px); */ 9 | border-style: solid; 10 | margin:auto; 11 | z-index:0; /* z-index of 0 will ensure that our map controls dont overlap the dyanmics drop downs. */ 12 | } 13 | 14 | #mapInfoDiv { 15 | height: 25px; 16 | position: relative; 17 | bottom: 0; 18 | margin-top: 5px; 19 | margin-left: 10px; 20 | color: #333333; 21 | font-size: 12px; 22 | } 23 | 24 | #invalidSpan { 25 | text-decoration: underline; 26 | color: #3b79b7; 27 | } 28 | 29 | @keyframes spinner-line-fade-more { 30 | 0%, 100% { 31 | opacity: 0; /* minimum opacity */ 32 | } 33 | 1% { 34 | opacity: 1; 35 | } 36 | } 37 | 38 | @keyframes spinner-line-fade-quick { 39 | 0%, 39%, 100% { 40 | opacity: 0.25; /* minimum opacity */ 41 | } 42 | 40% { 43 | opacity: 1; 44 | } 45 | } 46 | 47 | @keyframes spinner-line-fade-default { 48 | 0%, 100% { 49 | opacity: 0.22; /* minimum opacity */ 50 | } 51 | 1% { 52 | opacity: 1; 53 | } 54 | } 55 | 56 | @keyframes spinner-line-shrink { 57 | 0%, 25%, 100% { 58 | /* minimum scale and opacity */ 59 | transform: scale(0.5); 60 | opacity: 0.25; 61 | } 62 | 26% { 63 | transform: scale(1); 64 | opacity: 1; 65 | } 66 | } -------------------------------------------------------------------------------- /BingMapsGrid/BingMapsGrid/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/BingMapsGrid/BingMapsGrid/preview.png -------------------------------------------------------------------------------- /BingMapsGrid/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /BingMapsGrid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/node": "^10.17.24", 17 | "is-hexcolor": "^1.0.0", 18 | "spin.js": "^4.1.0" 19 | }, 20 | "devDependencies": { 21 | "bingmaps": "^2.0.3", 22 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 23 | "@types/powerapps-component-framework": "^1.3", 24 | "@typescript-eslint/eslint-plugin": "^8.18.0", 25 | "@typescript-eslint/parser": "^8.18.0", 26 | "eslint": "^8.57.0", 27 | "eslint-plugin-import": "^2.31.0", 28 | "eslint-plugin-node": "^11.1.0", 29 | "eslint-plugin-promise": "^7.1.0", 30 | "pcf-scripts": "^1", 31 | "pcf-start": "^1", 32 | "typescript": "^4.9.5" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /BingMapsGrid/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /BingMapsGrid/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /BooleanOptionset/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /BooleanOptionset/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /BooleanOptionset/BooleanOptionset/BooleanOptionsetControl/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj -------------------------------------------------------------------------------- /BooleanOptionset/BooleanOptionset/BooleanOptionsetControl/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /BooleanOptionset/BooleanOptionset/BooleanOptionsetControl/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /BooleanOptionset/README.md: -------------------------------------------------------------------------------- 1 | BOOLEAN OPTIONSET 2 | ================ 3 | 4 | A PCF Control to allow you to set a Boolean field to a drop down instead of a toggle. Typically Booleans fields can be made into drop down easily using the form editor but on certain version of dynamics there is a bug which only allows Toggle style fields within Business Process Flow (BPF) screens. This control will allow you to have a drop down again on those BPF forms. 5 | 6 | # Installation Usage 7 | [Download Latest](https://github.com/rwilson504/PCFControls/releases/latest/download/BooleanOptionsetControl_managed.zip) 8 | 9 | To utilize this control you can follow the [these instructions](https://powerusers.microsoft.com/t5/Power-Automate-Community-Blog/Preview-Custom-Controls-in-Business-Process-Flows/ba-p/263237) for adding custom PCF components to BPF forms. 10 | -------------------------------------------------------------------------------- /BooleanOptionset/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /BooleanOptionset/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/node": "^10.17.60" 17 | }, 18 | "devDependencies": { 19 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 20 | "@types/powerapps-component-framework": "^1.3", 21 | "@typescript-eslint/eslint-plugin": "^8.18.0", 22 | "@typescript-eslint/parser": "^8.18.0", 23 | "eslint": "^8.57.0", 24 | "eslint-plugin-import": "^2.31.0", 25 | "eslint-plugin-node": "^11.1.0", 26 | "eslint-plugin-promise": "^7.1.0", 27 | "pcf-scripts": "^1", 28 | "pcf-start": "^1", 29 | "typescript": "^4.9.5" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /BooleanOptionset/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /BooleanOptionset/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /Calendar/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Calendar/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /Calendar/Calendar/CalendarControl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /Calendar/Calendar/CalendarControl/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /Calendar/Calendar/CalendarControl/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /Calendar/Calendar/accessors/tooltipAccessor.tsx: -------------------------------------------------------------------------------- 1 | import { IEvent } from "../types/IEvent"; 2 | 3 | /** 4 | * Returns a tooltip string for a calendar event. 5 | * If the event has a description, the tooltip will be: 6 | * Title\nDescription 7 | * Otherwise, just the title. 8 | */ 9 | export function tooltipAccessor(event: IEvent): string { 10 | if (event.description) { 11 | // Use a line break for HTML tooltips, or \n for plain text 12 | return `${event.title}\n${event.description}`; 13 | } 14 | return `${event.title}`; 15 | } 16 | -------------------------------------------------------------------------------- /Calendar/Calendar/getters/dayPropsGetter.ts: -------------------------------------------------------------------------------- 1 | import { Moment, MomentInput } from "moment"; 2 | import * as Color from "color"; 3 | 4 | export function dayPropsGetter( 5 | date: Date, 6 | calendarTodayBackgroundColor: Color | string, 7 | weekendColor: Color | string, 8 | momentInstance: (input?: MomentInput) => Moment 9 | ) { 10 | // Check if the day is today 11 | if (momentInstance(date).startOf("day").isSame(momentInstance().startOf("day"))) 12 | return { 13 | style: { 14 | backgroundColor: calendarTodayBackgroundColor.toString(), 15 | }, 16 | }; 17 | // Check if the day is a weekend (Saturday or Sunday) 18 | if (momentInstance(date).day() === 0 || momentInstance(date).day() === 6) { 19 | return { 20 | style: { 21 | backgroundColor: weekendColor.toString(), 22 | }, 23 | }; 24 | } 25 | return {}; 26 | } 27 | -------------------------------------------------------------------------------- /Calendar/Calendar/getters/eventPropsGetter.ts: -------------------------------------------------------------------------------- 1 | import { IEvent } from "../types"; 2 | import * as Color from "color"; 3 | 4 | export function eventPropsGetter( 5 | event: IEvent, 6 | isEventSelectable: boolean, 7 | eventDefaultBackgroundColor: Color | string, 8 | calendarBorderColor: Color | string 9 | ) { 10 | return { 11 | style: { 12 | cursor: isEventSelectable ? "pointer" : "default", 13 | backgroundColor: event.color || eventDefaultBackgroundColor.toString(), 14 | color: Color(event.color || eventDefaultBackgroundColor).isDark() 15 | ? "#fff" 16 | : "#000", 17 | borderColor: calendarBorderColor.toString(), 18 | }, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /Calendar/Calendar/getters/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./dayPropsGetter"; 2 | export * from "./eventPropsGetter"; -------------------------------------------------------------------------------- /Calendar/Calendar/handlers/handleEventKeyPress.ts: -------------------------------------------------------------------------------- 1 | import * as CalendarUtils from "../utils"; 2 | import { IEvent } from "../types"; 3 | import * as React from "react"; 4 | 5 | export function handleEventKeyPress(_handleEventSelected: (event: IEvent) => void) { 6 | return (event: IEvent, e: React.SyntheticEvent) => { 7 | const keyboardEvent = e as unknown as React.KeyboardEvent; 8 | if (CalendarUtils.VALID_KEYS.includes(keyboardEvent.key)) { 9 | _handleEventSelected(event); 10 | } 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /Calendar/Calendar/handlers/handleEventSelected.ts: -------------------------------------------------------------------------------- 1 | import { IInputs } from "../generated/ManifestTypes"; 2 | import { IEvent } from "../types"; 3 | 4 | export function handleEventSelected( 5 | isEventSelectable: boolean, 6 | onClickSelectedRecord: (id: string) => void, 7 | pcfContext: ComponentFramework.Context 8 | ) { 9 | return (event: IEvent) => { 10 | if (!isEventSelectable) { 11 | return; 12 | } 13 | 14 | const eventId = event.id as string; 15 | onClickSelectedRecord(eventId); 16 | 17 | if (pcfContext.mode.allocatedHeight === -1) { 18 | pcfContext.navigation.openForm({ 19 | entityId: eventId, 20 | entityName: pcfContext.parameters.calendarDataSet.getTargetEntityType(), 21 | openInNewWindow: false, 22 | }); 23 | } 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /Calendar/Calendar/handlers/handleNavigate.ts: -------------------------------------------------------------------------------- 1 | import * as moment from "moment"; 2 | 3 | export function handleNavigate( 4 | setCalendarDate: (date: Date) => void, 5 | setCalendarView?: (view: string) => void 6 | ) { 7 | return (date: Date, view: string, action: string) => { 8 | setCalendarDate(moment(date).toDate()); 9 | if (setCalendarView && view) { 10 | setCalendarView(view); 11 | } 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /Calendar/Calendar/handlers/handleOnView.ts: -------------------------------------------------------------------------------- 1 | // No transformation, just set the view from the event 2 | export function handleOnView(setCalendarView: (view: string) => void) { 3 | return (view: string) => { 4 | setCalendarView(view); 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /Calendar/Calendar/handlers/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./handleNavigate"; 2 | export * from "./handleOnView"; 3 | export * from "./handleEventKeyPress"; 4 | export * from "./handleEventSelected"; 5 | export * from "./handleSlotSelect"; -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./useCalendarHourRange"; 2 | export * from "./useDayLayoutAlgorithm"; 3 | export * from "./useEventSelectable"; 4 | export * from "./useCalendarStepAndTimeslots"; 5 | export * from "./useCalendarSelectable"; 6 | export * from "./useCalendarPopup" 7 | export * from "./useCalendarDate" 8 | export * from "./useEventHeaderFormat"; 9 | export * from "./useCalendarView"; 10 | export * from "./useCalendarData"; 11 | export * from "./useCalendarColors"; -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useCalendarData.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { Resource, Keys, IEvent } from "../types"; 3 | import * as CalendarUtils from "../utils"; 4 | import { IInputs } from "../generated/ManifestTypes"; 5 | 6 | export function useCalendarData(pcfContext: ComponentFramework.Context) { 7 | const [calendarData, setCalendarData] = useState<{ 8 | resources: Resource[] | undefined; 9 | events: IEvent[]; 10 | keys: Keys | undefined; 11 | }>({ resources: [], events: [], keys: undefined }); 12 | 13 | useEffect(() => { 14 | async function asyncCalendarData() { 15 | let keys = calendarData.keys; 16 | if (!keys) { 17 | keys = await CalendarUtils.getKeys(pcfContext); 18 | } 19 | 20 | const dataSet = pcfContext.parameters.calendarDataSet; 21 | if (dataSet.loading === false) { 22 | const calendarDataResult = await CalendarUtils.getCalendarData( 23 | pcfContext, 24 | keys 25 | ); 26 | 27 | setCalendarData({ 28 | resources: 29 | calendarDataResult.resources && 30 | calendarDataResult.resources.length > 0 31 | ? calendarDataResult.resources 32 | : undefined, 33 | events: calendarDataResult.events || [], 34 | keys: calendarDataResult.keys || undefined, 35 | }); 36 | } 37 | } 38 | asyncCalendarData(); 39 | }, [pcfContext.parameters.calendarDataSet.records]); 40 | 41 | return [calendarData, setCalendarData] as const; 42 | } 43 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useCalendarDate.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { Moment, MomentInput } from "moment"; 3 | import { IInputs } from "../generated/ManifestTypes"; 4 | 5 | export function useCalendarDate(pcfContext: ComponentFramework.Context, momentInstance: (input?: MomentInput) => Moment) { 6 | const [calendarDate, setCalendarDate] = useState( 7 | pcfContext.parameters.calendarDate?.raw?.getTime() === 0 8 | ? momentInstance().toDate() 9 | : pcfContext.parameters.calendarDate?.raw || momentInstance().toDate() 10 | ); 11 | 12 | useEffect(() => { 13 | if ( 14 | pcfContext.parameters.calendarDate?.raw?.getTime() !== 0 && 15 | !momentInstance(calendarDate).isSame(pcfContext.parameters.calendarDate.raw) 16 | ) { 17 | setCalendarDate(pcfContext.parameters.calendarDate.raw as Date); 18 | } 19 | // Only update from prop if prop changes and is different from state 20 | // This allows navigation to work without being overwritten by the prop 21 | }, [pcfContext.parameters.calendarDate?.raw?.getTime()]); 22 | 23 | return [calendarDate, setCalendarDate] as const; 24 | } 25 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useCalendarHourRange.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState, useMemo } from "react"; 2 | import * as CalendarUtils from "../utils"; 3 | import { IInputs } from "../generated/ManifestTypes"; 4 | 5 | export function useCalendarHourRange(pcfContext: ComponentFramework.Context, momentInstance: typeof import("moment")) { 6 | const [minHour, setMinHour] = useState( 7 | pcfContext.parameters.calendarMinHour?.raw ?? CalendarUtils.DEFAULT_MIN_HOUR 8 | ); 9 | const [maxHour, setMaxHour] = useState( 10 | pcfContext.parameters.calendarMaxHour?.raw ?? CalendarUtils.DEFAULT_MAX_HOUR 11 | ); 12 | 13 | useEffect(() => { 14 | const newMinHour = 15 | pcfContext.parameters.calendarMinHour?.raw ?? CalendarUtils.DEFAULT_MIN_HOUR; 16 | const newMaxHour = 17 | pcfContext.parameters.calendarMaxHour?.raw ?? CalendarUtils.DEFAULT_MAX_HOUR; 18 | 19 | setMinHour(newMinHour); 20 | setMaxHour(newMaxHour); 21 | }, [ 22 | pcfContext.parameters.calendarMinHour?.raw, 23 | pcfContext.parameters.calendarMaxHour?.raw, 24 | ]); 25 | 26 | const min = useMemo( 27 | () => momentInstance(`${minHour}:00`, "HH:mm").toDate(), 28 | [minHour, momentInstance] 29 | ); 30 | const max = useMemo( 31 | () => momentInstance(`${maxHour}:59:59`, "HH:mm:ss").toDate(), 32 | [maxHour, momentInstance] 33 | ); 34 | 35 | return { min, max }; 36 | } -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useCalendarPopup.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import * as CalendarUtils from "../utils"; 3 | import { IInputs } from "../generated/ManifestTypes"; 4 | 5 | export function useCalendarPopup(pcfContext: ComponentFramework.Context) { 6 | const [calendarPopup, setCalendarPopup] = useState( 7 | pcfContext.parameters.calendarPopup?.raw?.toLowerCase() === "false" 8 | ? false 9 | : CalendarUtils.DEFAULT_POPUP 10 | ); 11 | 12 | useEffect(() => { 13 | const popupValue = 14 | pcfContext.parameters.calendarPopup?.raw?.toLowerCase() === "false" 15 | ? false 16 | : CalendarUtils.DEFAULT_POPUP; 17 | setCalendarPopup(popupValue); 18 | }, [pcfContext.parameters.calendarPopup?.raw]); 19 | 20 | return calendarPopup; 21 | } 22 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useCalendarSelectable.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import * as CalendarUtils from "../utils"; 3 | import { IInputs } from "../generated/ManifestTypes"; 4 | 5 | export function useCalendarSelectable(pcfContext: ComponentFramework.Context) { 6 | const [calendarSelectable, setCalendarSelectable] = useState( 7 | pcfContext.parameters.calendarSelectable?.raw?.toLowerCase() === "false" 8 | ? false 9 | : CalendarUtils.DEFAULT_SELECTABLE 10 | ); 11 | 12 | useEffect(() => { 13 | const selectableValue = 14 | pcfContext.parameters.calendarSelectable?.raw?.toLowerCase() === "false" 15 | ? false 16 | : CalendarUtils.DEFAULT_SELECTABLE; 17 | setCalendarSelectable(selectableValue); 18 | }, [pcfContext.parameters.calendarSelectable?.raw]); 19 | 20 | return calendarSelectable; 21 | } 22 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useCalendarStepAndTimeslots.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import * as CalendarUtils from "../utils"; 3 | import { IInputs } from "../generated/ManifestTypes"; 4 | 5 | export function useCalendarStepAndTimeslots(pcfContext: ComponentFramework.Context) { 6 | const [step, setStep] = useState( 7 | pcfContext.parameters.calendarStep?.raw ?? CalendarUtils.DEFAULT_STEP 8 | ); 9 | const [timeslots, setTimeslots] = useState( 10 | pcfContext.parameters.calendarTimeSlots?.raw ?? CalendarUtils.DEFAULT_TIMESLOTS 11 | ); 12 | 13 | useEffect(() => { 14 | const newStep = 15 | pcfContext.parameters.calendarStep?.raw ?? CalendarUtils.DEFAULT_STEP; 16 | const newTimeslots = 17 | pcfContext.parameters.calendarTimeSlots?.raw ?? CalendarUtils.DEFAULT_TIMESLOTS; 18 | setStep(newStep); 19 | setTimeslots(newTimeslots); 20 | }, [ 21 | pcfContext.parameters.calendarStep?.raw, 22 | pcfContext.parameters.calendarTimeSlots?.raw, 23 | ]); 24 | 25 | return { step, timeslots }; 26 | } 27 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useCalendarView.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { getCalendarView } from "../utils/CalendarHelpers"; 3 | import { View, ViewProps } from "react-big-calendar"; 4 | import { Resource } from "../types"; 5 | 6 | export function useCalendarView(calendarViews: View[], calendarViewRaw: string) { 7 | const [calendarView, setCalendarView] = useState( 8 | getCalendarView(calendarViews, calendarViewRaw || "") 9 | ); 10 | 11 | useEffect(() => { 12 | if ( 13 | calendarViewRaw && 14 | calendarView !== calendarViewRaw 15 | ) { 16 | setCalendarView(getCalendarView(calendarViews, calendarViewRaw)); 17 | } 18 | // Only update from prop if prop changes and is different from state 19 | // This allows view changes from the calendar header to work without being overwritten by the prop 20 | }, [calendarViewRaw]); 21 | 22 | return [calendarView, setCalendarView] as const; 23 | } 24 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useDayLayoutAlgorithm.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { DayLayoutAlgorithm } from "react-big-calendar"; 3 | import * as CalendarUtils from "../utils"; 4 | import { IInputs } from "../generated/ManifestTypes"; 5 | 6 | export function useDayLayoutAlgorithm(pcfContext: ComponentFramework.Context) { 7 | const [dayLayoutAlgorithm, setDayLayoutAlgorithm] = useState( 8 | (pcfContext.parameters.dayLayoutAlgorithm?.raw as DayLayoutAlgorithm) || CalendarUtils.DEFAULT_LAYOUT_ALGORITHM 9 | ); 10 | 11 | useEffect(() => { 12 | const algorithm = 13 | (pcfContext.parameters.dayLayoutAlgorithm?.raw as DayLayoutAlgorithm) || CalendarUtils.DEFAULT_LAYOUT_ALGORITHM; 14 | setDayLayoutAlgorithm(algorithm); 15 | }, [pcfContext.parameters.dayLayoutAlgorithm?.raw]); 16 | 17 | return dayLayoutAlgorithm; 18 | } 19 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useEventHeaderFormat.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { IInputs } from "../generated/ManifestTypes"; 3 | 4 | export function useEventHeaderFormat(pcfContext: ComponentFramework.Context) { 5 | const [eventHeaderFormat, setEventHeaderFormat] = useState( 6 | pcfContext.parameters.eventHeaderFormat?.raw || "0" 7 | ); 8 | 9 | useEffect(() => { 10 | const formatValue = pcfContext.parameters.eventHeaderFormat?.raw || "0"; 11 | setEventHeaderFormat(formatValue); 12 | }, [pcfContext.parameters.eventHeaderFormat?.raw]); 13 | 14 | return eventHeaderFormat; 15 | } 16 | -------------------------------------------------------------------------------- /Calendar/Calendar/hooks/useEventSelectable.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import * as CalendarUtils from "../utils/Constants"; 3 | import { IInputs } from "../generated/ManifestTypes"; 4 | 5 | export function useEventSelectable(pcfContext: ComponentFramework.Context) { 6 | const [isEventSelectable, setIsEventSelectable] = useState( 7 | pcfContext.parameters.eventSelectable?.raw?.toLowerCase() === "false" 8 | ? false 9 | : CalendarUtils.DEFAULT_EVENT_SELECTABLE 10 | ); 11 | 12 | useEffect(() => { 13 | const selectableValue = 14 | pcfContext.parameters.eventSelectable?.raw?.toLowerCase() === "false" 15 | ? false 16 | : CalendarUtils.DEFAULT_EVENT_SELECTABLE; 17 | setIsEventSelectable(selectableValue); 18 | }, [pcfContext.parameters.eventSelectable?.raw]); 19 | 20 | return isEventSelectable; 21 | } 22 | -------------------------------------------------------------------------------- /Calendar/Calendar/renderers/agendaEventRenderer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Color from "color"; 3 | 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | export function agendaEventRenderer({ event }: any, isEventSelectable: boolean, eventDefaultBackgroundColor: any) { 6 | return ( 7 | 21 | {event.title} 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /Calendar/Calendar/renderers/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./resourceHeaderRenderer"; 2 | export * from "./agendaEventRenderer" 3 | export * from "./timeGutterHeaderRenderer" 4 | export * from "./timeSlotWrapperRenderer" -------------------------------------------------------------------------------- /Calendar/Calendar/renderers/resourceHeaderRenderer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 4 | export function resourceHeaderRenderer({ label }: any) { 5 | return {label}; 6 | } 7 | -------------------------------------------------------------------------------- /Calendar/Calendar/renderers/timeGutterHeaderRenderer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 4 | export function timeGutterHeaderRenderer(ref: any) { 5 | return ( 6 | 10 | {ref ? ref.props.messages.allDay : ""} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /Calendar/Calendar/renderers/timeSlotWrapperRenderer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | // Modularized time slot wrapper renderer for react-big-calendar 4 | // Encapsulate minHeight logic here, allowing for dynamic calculation if needed 5 | export function timeSlotWrapperRenderer(props: { children?: React.ReactNode; timeslots?: number }) { 6 | const { children, timeslots } = props; 7 | let minHeight = 40; 8 | if (typeof timeslots === "number") { 9 | minHeight = timeslots === 1 ? 40 : 20; 10 | } 11 | return
{children}
; 12 | } 13 | -------------------------------------------------------------------------------- /Calendar/Calendar/types/IEvent.ts: -------------------------------------------------------------------------------- 1 | import { Event } from "react-big-calendar"; 2 | 3 | //extend the event interface to include additional properties we wil use. 4 | export interface IEvent extends Event { 5 | id?: string; 6 | color?: string; 7 | description?: string; 8 | } 9 | -------------------------------------------------------------------------------- /Calendar/Calendar/types/Keys.ts: -------------------------------------------------------------------------------- 1 | export interface Keys { 2 | id: string; 3 | name: string; 4 | description?: string; 5 | start: string; 6 | end: string; 7 | eventColor?: string; 8 | resource?: string; 9 | resourceName?: string; 10 | resourceId?: string; 11 | resourceEtn?: string; 12 | resourceGetAllInModel?: boolean; 13 | } -------------------------------------------------------------------------------- /Calendar/Calendar/types/Resource.ts: -------------------------------------------------------------------------------- 1 | export interface Resource { 2 | id: string; 3 | title: string; 4 | etn?: string; // Entity type name, optional 5 | } -------------------------------------------------------------------------------- /Calendar/Calendar/types/SlotInfo.ts: -------------------------------------------------------------------------------- 1 | export interface SlotInfo { 2 | start: Date; 3 | end: Date; 4 | resourceId?: string; 5 | } 6 | -------------------------------------------------------------------------------- /Calendar/Calendar/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./IEvent" 2 | export * from "./Keys" 3 | export * from "./Resource" 4 | -------------------------------------------------------------------------------- /Calendar/Calendar/types/is-hexcolor.d.ts: -------------------------------------------------------------------------------- 1 | declare module "is-hexcolor" { 2 | const isHexColor: (color: string) => boolean; 3 | export default isHexColor; 4 | } 5 | -------------------------------------------------------------------------------- /Calendar/Calendar/types/react-big-calendar.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | declare module 'react-big-calendar/lib/Week' { 3 | const Week: any; 4 | export default Week; 5 | } 6 | 7 | declare module 'react-big-calendar/lib/TimeGrid' { 8 | const TimeGrid: any; 9 | export default TimeGrid; 10 | } -------------------------------------------------------------------------------- /Calendar/Calendar/utils/Constants.ts: -------------------------------------------------------------------------------- 1 | import { DayLayoutAlgorithm } from "react-big-calendar"; 2 | 3 | export const CALENDAR_VIEWS = ["month", "week", "work_week", "day", "agenda"] as string[]; 4 | 5 | export const DEFAULT_EVENT_COLOR = "#3174ad"; 6 | export const DEFAULT_TODAY_BACKGROUND_COLOR = "#eaf6ff"; 7 | export const DEFAULT_TEXT_COLOR = "#666666"; 8 | export const DEFAULT_BORDER_COLOR = "#dddddd"; 9 | export const DEFAULT_TIMEBAR_BACKGROUND_COLOR = "#ffffff"; 10 | export const DEFAULT_WEEKEND_BACKGROUND_COLOR = "#00000000"; 11 | 12 | export const DEFAULT_MIN_HOUR = 0; 13 | export const DEFAULT_MAX_HOUR = 23; 14 | export const DEFAULT_STEP = 30; // 30 minutes per time slot 15 | export const DEFAULT_TIMESLOTS = 2; // Two slots per hour 16 | export const DEFAULT_LAYOUT_ALGORITHM: DayLayoutAlgorithm = "overlap"; 17 | export const VALID_KEYS = ["Enter", " "]; 18 | export const DEFAULT_SELECTABLE = true; 19 | export const DEFAULT_EVENT_SELECTABLE = true; 20 | export const DEFAULT_POPUP = true; -------------------------------------------------------------------------------- /Calendar/Calendar/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./DataHelpers" 2 | export * from "./CalendarHelpers" 3 | export * from "./Constants" -------------------------------------------------------------------------------- /Calendar/Sample/CanvasCalendar_1.0.0.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/Sample/CanvasCalendar_1.0.0.5.zip -------------------------------------------------------------------------------- /Calendar/Sample/CanvasCalendar_1.0.0.5_managed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/Sample/CanvasCalendar_1.0.0.5_managed.zip -------------------------------------------------------------------------------- /Calendar/Sample/CanvasCalendar_1_0_0_4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/Sample/CanvasCalendar_1_0_0_4.zip -------------------------------------------------------------------------------- /Calendar/Sample/CanvasCalendar_1_0_0_4_managed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/Sample/CanvasCalendar_1_0_0_4_managed.zip -------------------------------------------------------------------------------- /Calendar/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /Calendar/images/CalendarControlForCanvasAndModel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CalendarControlForCanvasAndModel.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarAllResourcesAdvancedProps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarAllResourcesAdvancedProps.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarAllResourcesDataSource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarAllResourcesDataSource.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarAllResourcesResourceHeader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarAllResourcesResourceHeader.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarDateControlProp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarDateControlProp.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarDateOnChange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarDateOnChange.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarDateOnStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarDateOnStart.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarDatePickerProps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarDatePickerProps.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarEventsOnly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarEventsOnly.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarEventsOnlyAdvancedProps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarEventsOnlyAdvancedProps.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarEventsOnlyDataSource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarEventsOnlyDataSource.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarEventsOnlyOnLoad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarEventsOnlyOnLoad.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarOnChange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarOnChange.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarOnChangeProperties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarOnChangeProperties.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarResourcesWithEventsAdvancedProps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarResourcesWithEventsAdvancedProps.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarResourcesWithEventsData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarResourcesWithEventsData.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarResourcesWithEventsDataSource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarResourcesWithEventsDataSource.png -------------------------------------------------------------------------------- /Calendar/images/CanvasCalendarResourcesWithEventsResourceHeader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/CanvasCalendarResourcesWithEventsResourceHeader.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarAddColumns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarAddColumns.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarAddControl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarAddControl.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarSelectCalendarControl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarSelectCalendarControl.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarSelectProperties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarSelectProperties.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarShowAs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarShowAs.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarShowAsCalendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarShowAsCalendar.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarSubGrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarSubGrid.png -------------------------------------------------------------------------------- /Calendar/images/ModelCalendarSubGridHeight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/ModelCalendarSubGridHeight.png -------------------------------------------------------------------------------- /Calendar/images/calendarcontrol.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Calendar/images/calendarcontrol.gif -------------------------------------------------------------------------------- /Calendar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@fluentui/react": "^8.121", 17 | "@types/color": "^3.0.2", 18 | "@types/node": "^14.17.9", 19 | "@types/powerapps-component-framework": "^1.3", 20 | "@types/react-big-calendar": "^1.16", 21 | "color": "^3.2.1", 22 | "css-vars-ponyfill": "^2.4.9", 23 | "is-hexcolor": "^1.0.0", 24 | "lcid": "^3.1.1", 25 | "moment": "^2.29.1", 26 | "react": "^18.2", 27 | "react-big-calendar": "^1.17", 28 | "react-dom": "^18.2", 29 | "react-swipeable": "^7" 30 | }, 31 | "devDependencies": { 32 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 33 | "@typescript-eslint/eslint-plugin": "^8.18.0", 34 | "@typescript-eslint/parser": "^8.18.0", 35 | "eslint": "^8.57.0", 36 | "eslint-plugin-import": "^2.31.0", 37 | "eslint-plugin-node": "^11.1.0", 38 | "eslint-plugin-promise": "^7.1.0", 39 | "pcf-scripts": "^1", 40 | "pcf-start": "^1", 41 | "typescript": "^4.9.5" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Calendar/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /Calendar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"] 5 | } 6 | } -------------------------------------------------------------------------------- /CanvasFileDownloader/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CanvasFileDownloader/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /CanvasFileDownloader/CanvasFileDownloader/ControlManifest.Input.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /CanvasFileDownloader/Solution/CanvasFileDownloaderControl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /CanvasFileDownloader/Solution/CanvasFileDownloaderControl/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /CanvasFileDownloader/Solution/CanvasFileDownloaderControl/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /CanvasFileDownloader/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /CanvasFileDownloader/images/AddComponentToForm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileDownloader/images/AddComponentToForm.png -------------------------------------------------------------------------------- /CanvasFileDownloader/images/CanvasFileDownloader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileDownloader/images/CanvasFileDownloader.png -------------------------------------------------------------------------------- /CanvasFileDownloader/images/ComponentProperties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileDownloader/images/ComponentProperties.png -------------------------------------------------------------------------------- /CanvasFileDownloader/images/DownloadButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileDownloader/images/DownloadButton.png -------------------------------------------------------------------------------- /CanvasFileDownloader/images/FileDownloaded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileDownloader/images/FileDownloaded.png -------------------------------------------------------------------------------- /CanvasFileDownloader/images/ImportComponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileDownloader/images/ImportComponent.png -------------------------------------------------------------------------------- /CanvasFileDownloader/images/ImportComponentRibbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileDownloader/images/ImportComponentRibbon.png -------------------------------------------------------------------------------- /CanvasFileDownloader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/node": "^18.19", 17 | "@types/powerapps-component-framework": "^1.3" 18 | }, 19 | "devDependencies": { 20 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 21 | "@typescript-eslint/eslint-plugin": "^8.18.0", 22 | "@typescript-eslint/parser": "^8.18.0", 23 | "eslint": "^8.57.0", 24 | "eslint-plugin-import": "^2.31.0", 25 | "eslint-plugin-node": "^11.1.0", 26 | "eslint-plugin-promise": "^7.1.0", 27 | "pcf-scripts": "^1", 28 | "pcf-start": "^1", 29 | "typescript": "^4.9.5" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CanvasFileDownloader/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /CanvasFileDownloader/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /CanvasFileUploader/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CanvasFileUploader/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /CanvasFileUploader/Solution/CanvasFileUploaderComponent/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /CanvasFileUploader/Solution/CanvasFileUploaderComponent/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /CanvasFileUploader/Solution/CanvasFileUploaderComponent/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /CanvasFileUploader/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /CanvasFileUploader/images/AddComponentToForm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/AddComponentToForm.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/CanvasComponentUpload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/CanvasComponentUpload.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/CanvasFileUploader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/CanvasFileUploader.gif -------------------------------------------------------------------------------- /CanvasFileUploader/images/ComponentProperties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/ComponentProperties.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/CustomAppStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/CustomAppStart.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/ImageViewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/ImageViewer.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/ImportComponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/ImportComponent.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/ImportComponentRibbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/ImportComponentRibbon.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/PDFViewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/PDFViewer.png -------------------------------------------------------------------------------- /CanvasFileUploader/images/StandardInput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/CanvasFileUploader/images/StandardInput.png -------------------------------------------------------------------------------- /CanvasFileUploader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/node": "^18.19", 17 | "@types/powerapps-component-framework": "^1.3" 18 | }, 19 | "devDependencies": { 20 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 21 | "@typescript-eslint/eslint-plugin": "^8.18.0", 22 | "@typescript-eslint/parser": "^8.18.0", 23 | "eslint": "^8.57.0", 24 | "eslint-plugin-import": "^2.31.0", 25 | "eslint-plugin-node": "^11.1.0", 26 | "eslint-plugin-promise": "^7.1.0", 27 | "pcf-scripts": "^1", 28 | "pcf-start": "^1", 29 | "typescript": "^4.9.5" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CanvasFileUploader/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /CanvasFileUploader/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /ColorPicker/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ColorPicker/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /ColorPicker/ColorPicker/ControlManifest.Input.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ColorPicker/ColorPicker/ControlPicker/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj -------------------------------------------------------------------------------- /ColorPicker/ColorPicker/ControlPicker/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /ColorPicker/ColorPicker/ControlPicker/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /ColorPicker/ColorPicker/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/ColorPicker/ColorPicker/preview.png -------------------------------------------------------------------------------- /ColorPicker/README.md: -------------------------------------------------------------------------------- 1 | PCF/REACT COLOR PICKER 2 | ================ 3 | 4 | A PCF Control for choosing a color and setting it's value in a single line text field. 5 | 6 | # Overview 7 | 8 | [Download Latest](https://github.com/rwilson504/PCFControls/releases/latest/download/ColorPicker_managed.zip) 9 | 10 | This control utilizes React and the Office-Ui-Fabric to allow a user to pick a color and update the text field that the control is bound to. 11 | 12 | ![Demo Image](https://1.bp.blogspot.com/-DRZqFJPS1e8/XbtAv9zhLZI/AAAAAAABN1Y/Qt5eoWhmTBcW3tplwsLL2plE1bAOmQDGwCLcBGAsYHQ/s1600/PCFColorPicker.gif) 13 | Note - Image above shows the color field twice so that you see that the field is being updated. 14 | -------------------------------------------------------------------------------- /ColorPicker/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /ColorPicker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "office-ui-fabric-react": "^7.111.0", 17 | "react": "^16.13.1", 18 | "react-dom": "^16.13.1" 19 | }, 20 | "devDependencies": { 21 | "@types/node": "^10.17.21", 22 | "@types/react": "^16.9.34", 23 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 24 | "@types/powerapps-component-framework": "^1.3", 25 | "@typescript-eslint/eslint-plugin": "^8.18.0", 26 | "@typescript-eslint/parser": "^8.18.0", 27 | "eslint": "^8.57.0", 28 | "eslint-plugin-import": "^2.31.0", 29 | "eslint-plugin-node": "^11.1.0", 30 | "eslint-plugin-promise": "^7.1.0", 31 | "pcf-scripts": "^1", 32 | "pcf-start": "^1", 33 | "typescript": "^4.9.5" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ColorPicker/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /ColorPicker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /DadJoke/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /DadJoke/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /DadJoke/DadJoke/ControlManifest.Input.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /DadJoke/DadJoke/img/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/DadJoke/DadJoke/img/preview.png -------------------------------------------------------------------------------- /DadJoke/Solution/RAW!DadJoke/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /DadJoke/Solution/RAW!DadJoke/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /DadJoke/Solution/RAW!DadJoke/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /DadJoke/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": {}, 16 | "devDependencies": { 17 | "@types/node": "^16.4", 18 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 19 | "@types/powerapps-component-framework": "^1.3", 20 | "@typescript-eslint/eslint-plugin": "^8.18.0", 21 | "@typescript-eslint/parser": "^8.18.0", 22 | "eslint": "^8.57.0", 23 | "eslint-plugin-import": "^2.31.0", 24 | "eslint-plugin-node": "^11.1.0", 25 | "eslint-plugin-promise": "^7.1.0", 26 | "pcf-scripts": "^1", 27 | "pcf-start": "^1", 28 | "typescript": "^4.9.5" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DadJoke/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /DadJoke/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /DetailListGrid/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off", 25 | "@typescript-eslint/no-empty-object-type": "off" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DetailListGrid/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /DetailListGrid/DetailListGrid/DetailListGridControl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /DetailListGrid/DetailListGrid/DetailListGridControl/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /DetailListGrid/DetailListGrid/DetailListGridControl/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /DetailListGrid/DetailListGrid/css/DetailListGridControl.css: -------------------------------------------------------------------------------- 1 | #detailList { 2 | height: 100%; 3 | max-height: 100%; 4 | overflow: auto; 5 | } 6 | 7 | /* #detailList .ms-Viewport, 8 | #detailList .ms-DetailsList, 9 | #detailList .ms-DetailsList-contentWrapper, 10 | #detailList .ms-DetailsList.list, 11 | #detailList .ms-DetailsList.list > div:first-child { 12 | height: 100%; 13 | } */ 14 | 15 | #detailList .ms-DetailsHeader { 16 | padding-top: 0px; 17 | } 18 | 19 | #detailList .ms-DetailsHeader-cellName { 20 | color: #6E6F77; 21 | font-size: 12px; 22 | font-weight: normal; 23 | } 24 | 25 | #detailList .detailList-cell { 26 | font-size: 15px; 27 | color: #333; 28 | } 29 | 30 | .detailList-footer { 31 | display: inline-block; 32 | padding: 10px; 33 | } 34 | 35 | .detailList-gridLabels { 36 | color: #6E6F77; 37 | font-size: 12px; 38 | font-weight: normal; 39 | } -------------------------------------------------------------------------------- /DetailListGrid/README.md: -------------------------------------------------------------------------------- 1 | ![DetailsList Grid Control](https://github.com/rwilson504/Blogger/blob/master/Office-Fabric-UI-DetailsList-PCF/office-fabric-ui-detailslist.gif?raw=true) 2 | 3 | [Download Latest](https://github.com/rwilson504/PCFControls/releases/latest/download/DetailListGridControl_managed.zip) 4 | 5 | Allows you to simulate the out of the box grid and subgrid controls using the Office-UI-Fabric DetailsList control. It was built to provide a springboard when you need a customizable grid experience. This component re-creates a mojority of the capabilities available out of the box in less than 300 lines of code and demonstrates the following: 6 | 7 | * Using the DataSet within a React functional component. 8 | * Displaying and sorting data within the Office-UI-Fabric DetailsList component. 9 | * Rendering custom formats for data with the DetailsList component such as links for Entity References, email addresses, and phone numbers. 10 | * Displaying field data for related entities. 11 | * React Hooks - the component uses both useState and useEffect. 12 | * Loading more than 5k records in DataSet. 13 | * Retaining the use of the standard ribbon buttons by using the setSelectedRecordIds function on the DataSet. 14 | * Detecting and responding to control width updates. -------------------------------------------------------------------------------- /DetailListGrid/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /DetailListGrid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "rebuild": "pcf-scripts rebuild", 9 | "start": "pcf-scripts start" 10 | }, 11 | "dependencies": { 12 | "@types/node": "^10.17.35", 13 | "lcid": "^3.1.1", 14 | "office-ui-fabric-react": "^7.144.2", 15 | "react": "^16.13.1" 16 | }, 17 | "devDependencies": { 18 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 19 | "@types/powerapps-component-framework": "^1.3", 20 | "@typescript-eslint/eslint-plugin": "^8.18.0", 21 | "@typescript-eslint/parser": "^8.18.0", 22 | "eslint": "^8.57.0", 23 | "eslint-plugin-import": "^2.31.0", 24 | "eslint-plugin-node": "^11.1.0", 25 | "eslint-plugin-promise": "^7.1.0", 26 | "pcf-scripts": "^1", 27 | "pcf-start": "^1", 28 | "typescript": "^4.9.5" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DetailListGrid/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /DetailListGrid/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /DocxTemplatesCanvas/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:react/recommended" 9 | ], 10 | "globals": { 11 | "ComponentFramework": true 12 | }, 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { 15 | "ecmaVersion": 12, 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "@typescript-eslint" 20 | ], 21 | "rules": { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DocxTemplatesCanvas/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Sample/DocxTemplateSample_1_0_0_1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/DocxTemplatesCanvas/Sample/DocxTemplateSample_1_0_0_1.zip -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Sample/DocxTemplateSample_1_0_0_1_managed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/DocxTemplatesCanvas/Sample/DocxTemplateSample_1_0_0_1_managed.zip -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Sample/SampleTemplate.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/DocxTemplatesCanvas/Sample/SampleTemplate.docx -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Sample/SampleTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/DocxTemplatesCanvas/Sample/SampleTemplate.png -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Sample/contoso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/DocxTemplatesCanvas/Sample/contoso.png -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Solution/RAWDocxTemplatesCanvas/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Solution/RAWDocxTemplatesCanvas/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /DocxTemplatesCanvas/Solution/RAWDocxTemplatesCanvas/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /DocxTemplatesCanvas/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "pcfAllowCustomWebpack": "on" 3 | } -------------------------------------------------------------------------------- /DocxTemplatesCanvas/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/DocxTemplatesCanvas/image.png -------------------------------------------------------------------------------- /DocxTemplatesCanvas/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "rebuild": "pcf-scripts rebuild", 9 | "start": "pcf-scripts start", 10 | "refreshTypes": "pcf-scripts refreshTypes" 11 | }, 12 | "dependencies": { 13 | "base64-arraybuffer": "^1.0.2", 14 | "easy-template-x": "^3.0.2" 15 | }, 16 | "devDependencies": { 17 | "@types/base64-arraybuffer": "^0.2.0", 18 | "@types/node": "^16.4", 19 | "@types/powerapps-component-framework": "^1.3.0", 20 | "@typescript-eslint/eslint-plugin": "^4.29.0", 21 | "@typescript-eslint/parser": "^4.29.0", 22 | "clean-webpack-plugin": "^4.0.0", 23 | "eslint": "^7.32.0", 24 | "eslint-plugin-import": "^2.23.4", 25 | "eslint-plugin-node": "^11.1.0", 26 | "eslint-plugin-promise": "^5.1.0", 27 | "pcf-scripts": "^1", 28 | "pcf-start": "^1", 29 | "speed-measure-webpack-plugin": "^1.5.0", 30 | "typescript": "^4.3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DocxTemplatesCanvas/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /DocxTemplatesCanvas/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /DocxTemplatesCanvas/webpack.config.js: -------------------------------------------------------------------------------- 1 | const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); 2 | const smp = new SpeedMeasurePlugin(); 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 4 | 5 | module.exports = smp.wrap({ 6 | devtool: 'source-map', 7 | plugins: [ 8 | // will clean the build folder on successful build 9 | new CleanWebpackPlugin(), 10 | ] 11 | }); -------------------------------------------------------------------------------- /ExportPDFManager/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj 15 | 16 | # MSBuild Binary and Structured Log 17 | *.binlog 18 | 19 | # Visual Studio cache/options directory 20 | /.vs 21 | 22 | # macos 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/ExportPDFManagerApp.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { IdPrefixProvider, FluentProvider} from "@fluentui/react-components"; 3 | import { PcfContextProvider } from "./services/PcfContext"; 4 | import { PcfContextService, IPcfContextServiceProps } from "./services/PcfContextService"; 5 | import { ExportPDFManagerControl } from "./components/ExportPDFManager"; 6 | import { useStyles } from "./utils/styles"; 7 | 8 | export const ExportPDFManagerApp: React.FC = (props) => { 9 | const styles = useStyles(); 10 | // Create the context service. 11 | const pcfContextService = new PcfContextService({ context: props.context, instanceid: props.instanceid, height: props.height }); 12 | 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default ExportPDFManagerApp; -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/hooks/useDisabledStatus.ts: -------------------------------------------------------------------------------- 1 | // import { useState, useEffect } from "react"; 2 | // import { PcfContextService } from "../services/PcfContextService"; 3 | 4 | // export const useDisabledStatus = (pcfContextService: PcfContextService) => { 5 | // const [isDisabled, setIsDisabled] = useState(pcfContextService.isControlDisabled()); 6 | 7 | // useEffect(() => { 8 | // const interval = setInterval(() => { 9 | // // Poll or check for changes in the disabled state 10 | // const currentDisabledState = pcfContextService.isControlDisabled(); 11 | // setIsDisabled(currentDisabledState); 12 | // }, 1000); // Check every second (adjust as needed) 13 | 14 | // return () => clearInterval(interval); // Cleanup on unmount 15 | // }, [pcfContextService]); 16 | 17 | // return isDisabled; 18 | // }; -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/resources/ExportPDFManager.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/ExportPDFManager/ExportPDFManager/resources/ExportPDFManager.ts -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/services/PcfContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { PcfContextService } from './PcfContextService' 3 | 4 | interface PcfContextProviderProps { 5 | pcfcontext: PcfContextService, 6 | children: React.ReactNode 7 | } 8 | 9 | const PcfContext = React.createContext(undefined!) 10 | 11 | export const PcfContextProvider = ({ pcfcontext, children }: PcfContextProviderProps) => { 12 | return ( 13 | 14 | {children} 15 | 16 | ) 17 | } 18 | 19 | export const usePcfContext = () => { 20 | return React.useContext(PcfContext) 21 | } 22 | -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/types/PdfEntity.ts: -------------------------------------------------------------------------------- 1 | export interface PdfEntity { 2 | displayName: string; 3 | logicalName: string; 4 | }; 5 | -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/types/PdfSetting.ts: -------------------------------------------------------------------------------- 1 | export interface PdfSetting { 2 | id: string; 3 | isEnabled: boolean; 4 | settings: string; 5 | } 6 | -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/types/SaveState.ts: -------------------------------------------------------------------------------- 1 | export type SaveState = "initial" | "loading" | "loaded"; 2 | -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PdfEntity'; 2 | export * from './PdfSetting'; 3 | export * from './SaveState'; 4 | -------------------------------------------------------------------------------- /ExportPDFManager/ExportPDFManager/utils/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@fluentui/react-components"; 2 | 3 | export const useStyles = makeStyles({ 4 | root: { 5 | display: "flex", 6 | flexDirection: "column", 7 | width: "100%", 8 | boxSizing: "border-box", 9 | }, 10 | tooltip: { 11 | "& ul": { 12 | listStylePosition: "outside", 13 | paddingLeft: "15px", 14 | }, 15 | }, 16 | gridDiv: { 17 | flexGrow: 1, 18 | overflowY: "auto", 19 | }, 20 | dataGrid: { 21 | // minWidth: "550px" 22 | }, 23 | header: { 24 | display: "flex", 25 | justifyContent: "space-between", 26 | alignItems: "center", 27 | marginBottom: "10px", 28 | }, 29 | headerTitle: { 30 | display: "flex", 31 | alignItems: "center", 32 | columnGap: "8px", 33 | }, 34 | footer: { 35 | display: "flex", 36 | justifyContent: "flex-end", 37 | marginTop: "10px", 38 | }, 39 | }); 40 | -------------------------------------------------------------------------------- /ExportPDFManager/Solution/ExportPDFManagerControl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj 6 | 7 | # MSBuild Binary and Structured Log 8 | *.binlog 9 | -------------------------------------------------------------------------------- /ExportPDFManager/Solution/ExportPDFManagerControl/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /ExportPDFManager/Solution/ExportPDFManagerControl/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /ExportPDFManager/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import eslintjs from "@eslint/js"; 2 | import microsoftPowerApps from "@microsoft/eslint-plugin-power-apps"; 3 | import pluginPromise from "eslint-plugin-promise"; 4 | import reactPlugin from "eslint-plugin-react"; 5 | import globals from "globals"; 6 | import typescriptEslint from "typescript-eslint"; 7 | 8 | /** @type {import('eslint').Linter.Config[]} */ 9 | export default [ 10 | { 11 | ignores: ["**/generated"], 12 | }, 13 | eslintjs.configs.recommended, 14 | ...typescriptEslint.configs.recommendedTypeChecked, 15 | ...typescriptEslint.configs.stylisticTypeChecked, 16 | pluginPromise.configs["flat/recommended"], 17 | microsoftPowerApps.configs.paCheckerHosted, 18 | reactPlugin.configs.flat.recommended, 19 | { 20 | plugins: { 21 | "@microsoft/power-apps": microsoftPowerApps, 22 | }, 23 | 24 | languageOptions: { 25 | globals: { 26 | ...globals.browser, 27 | ComponentFramework: true, 28 | }, 29 | parserOptions: { 30 | ecmaVersion: 2020, 31 | sourceType: "module", 32 | projectService: true, 33 | tsconfigRootDir: import.meta.dirname, 34 | }, 35 | }, 36 | 37 | rules: { 38 | "@typescript-eslint/no-unused-vars": "off", 39 | }, 40 | settings: { 41 | react: { 42 | version: "detect", 43 | }, 44 | }, 45 | }, 46 | ]; 47 | -------------------------------------------------------------------------------- /ExportPDFManager/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "pcfAllowCustomWebpack": "on" 3 | } -------------------------------------------------------------------------------- /ExportPDFManager/images/2025-03-31_16-12-42.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/ExportPDFManager/images/2025-03-31_16-12-42.PNG -------------------------------------------------------------------------------- /ExportPDFManager/images/2025-03-31_16-13-13.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/ExportPDFManager/images/2025-03-31_16-13-13.PNG -------------------------------------------------------------------------------- /ExportPDFManager/images/2025-04-02_15-21-37.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/ExportPDFManager/images/2025-04-02_15-21-37.PNG -------------------------------------------------------------------------------- /ExportPDFManager/images/2025-04-02_15-22-37.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/ExportPDFManager/images/2025-04-02_15-22-37.PNG -------------------------------------------------------------------------------- /ExportPDFManager/images/Export PDF Manager.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/ExportPDFManager/images/Export PDF Manager.gif -------------------------------------------------------------------------------- /ExportPDFManager/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@fluentui/react-components": "9.46.2", 17 | "axios": "^1.8.3", 18 | "html-react-parser": "^5.2.2", 19 | "react": "16.14.0", 20 | "react-dom": "16.14.0", 21 | "uuidv4": "^6.2.13" 22 | }, 23 | "devDependencies": { 24 | "@eslint/js": "^9.17.0", 25 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 26 | "@types/powerapps-component-framework": "^1.3.15", 27 | "@types/react": "^16.14.60", 28 | "@types/react-dom": "^16.9.24", 29 | "clean-webpack-plugin": "^4.0.0", 30 | "eslint-plugin-promise": "^7.1.0", 31 | "eslint-plugin-react": "^7.37.2", 32 | "globals": "^15.13.0", 33 | "pcf-scripts": "^1", 34 | "pcf-start": "^1", 35 | "react": "^16.14.0", 36 | "speed-measure-webpack-plugin": "^1.5.0", 37 | "typescript": "^4.9.5", 38 | "typescript-eslint": "^8.18.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ExportPDFManager/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /ExportPDFManager/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | "module": "es2015", 6 | "moduleResolution": "node" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ExportPDFManager/webpack.config.js: -------------------------------------------------------------------------------- 1 | const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); 2 | const smp = new SpeedMeasurePlugin(); 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 4 | 5 | module.exports = smp.wrap({ 6 | devtool: 'source-map', 7 | plugins: [ 8 | // will clean the build folder on successful build 9 | new CleanWebpackPlugin(), 10 | ] 11 | }); -------------------------------------------------------------------------------- /Frame/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Frame/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /Frame/Sample/RAWFrameSample_1_0_0_5_managed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Frame/Sample/RAWFrameSample_1_0_0_5_managed.zip -------------------------------------------------------------------------------- /Frame/Solution/RAWframe/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /Frame/Solution/RAWframe/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /Frame/Solution/RAWframe/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /Frame/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /Frame/frame/ControlManifest.Input.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | SingleLine.Text 9 | SingleLine.TextArea 10 | SingleLine.URL 11 | Multiple 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Frame/images/RAWFrame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Frame/images/RAWFrame.png -------------------------------------------------------------------------------- /Frame/js/BackButton.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Page Title 7 | 8 | 13 | 14 | 15 | Go Back 16 | 17 | -------------------------------------------------------------------------------- /Frame/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/node": "^10.17.50", 17 | "valid-url": "^1.0.9" 18 | }, 19 | "devDependencies": { 20 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 21 | "@types/powerapps-component-framework": "^1.3", 22 | "@typescript-eslint/eslint-plugin": "^8.18.0", 23 | "@typescript-eslint/parser": "^8.18.0", 24 | "eslint": "^8.57.0", 25 | "eslint-plugin-import": "^2.31.0", 26 | "eslint-plugin-node": "^11.1.0", 27 | "eslint-plugin-promise": "^7.1.0", 28 | "pcf-scripts": "^1", 29 | "pcf-start": "^1", 30 | "typescript": "^4.9.5" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Frame/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /Frame/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Richard A Wilson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PDFFormFillCanvas/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:react/recommended" 9 | ], 10 | "globals": { 11 | "ComponentFramework": true 12 | }, 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { 15 | "ecmaVersion": 12, 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "@typescript-eslint" 20 | ], 21 | "rules": { 22 | } 23 | } -------------------------------------------------------------------------------- /PDFFormFillCanvas/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /PDFFormFillCanvas/Sample/PDFFormFiller_1_0_0_1_managed.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/PDFFormFillCanvas/Sample/PDFFormFiller_1_0_0_1_managed.zip -------------------------------------------------------------------------------- /PDFFormFillCanvas/Solutions/RAWPDFFormFillCanvas/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /PDFFormFillCanvas/Solutions/RAWPDFFormFillCanvas/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /PDFFormFillCanvas/Solutions/RAWPDFFormFillCanvas/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /PDFFormFillCanvas/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "pcfAllowCustomWebpack": "on" 3 | } -------------------------------------------------------------------------------- /PDFFormFillCanvas/images/ImportComponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/PDFFormFillCanvas/images/ImportComponent.png -------------------------------------------------------------------------------- /PDFFormFillCanvas/images/ImportComponentFromCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/PDFFormFillCanvas/images/ImportComponentFromCode.png -------------------------------------------------------------------------------- /PDFFormFillCanvas/images/PDFFormFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/PDFFormFillCanvas/images/PDFFormFill.png -------------------------------------------------------------------------------- /PDFFormFillCanvas/images/YouTube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/PDFFormFillCanvas/images/YouTube.png -------------------------------------------------------------------------------- /PDFFormFillCanvas/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "rebuild": "pcf-scripts rebuild", 9 | "start": "pcf-scripts start" 10 | }, 11 | "dependencies": { 12 | "@types/js-base64": "^3.0.0", 13 | "@types/node": "^10.12.18", 14 | "@types/powerapps-component-framework": "^1.0.0", 15 | "image-type": "^4.1.0", 16 | "js-base64": "^3.5.2", 17 | "pdf-lib": "^1.0.0" 18 | }, 19 | "devDependencies": { 20 | "@typescript-eslint/eslint-plugin": "^5.42.1", 21 | "@typescript-eslint/parser": "^5.42.1", 22 | "clean-webpack-plugin": "^4.0.0", 23 | "eslint": "^8.27.0", 24 | "eslint-plugin-import": "^2.26.0", 25 | "eslint-plugin-node": "^11.1.0", 26 | "eslint-plugin-promise": "^6.1.1", 27 | "eslint-plugin-react": "^7.31.10", 28 | "pcf-scripts": "^1.0.0", 29 | "pcf-start": "^1.0.0", 30 | "speed-measure-webpack-plugin": "^1.5.0", 31 | "typescript": "^4.3.5" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /PDFFormFillCanvas/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /PDFFormFillCanvas/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | "sourceMap": true 6 | } 7 | } -------------------------------------------------------------------------------- /PDFFormFillCanvas/webpack.config.js: -------------------------------------------------------------------------------- 1 | const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); 2 | const smp = new SpeedMeasurePlugin(); 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 4 | 5 | module.exports = smp.wrap({ 6 | devtool: 'source-map', 7 | plugins: [ 8 | // will clean the build folder on successful build 9 | new CleanWebpackPlugin(), 10 | ] 11 | }); -------------------------------------------------------------------------------- /PowerPagesFileManager/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj 15 | 16 | # MSBuild Binary and Structured Log 17 | *.binlog 18 | 19 | # Visual Studio cache/options directory 20 | /.vs 21 | 22 | # macos 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/PortalFilesApp.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { IdPrefixProvider, FluentProvider } from "@fluentui/react-components"; 3 | import { PcfContextProvider } from "./services/PcfContext"; 4 | import { PcfContextService, IPcfContextServiceProps } from "./services/PcfContextService"; 5 | import { AnnotationsGrid } from "./components/AnnotationsGrid"; 6 | 7 | export const PortalFilesApp: React.FC = (props) => { 8 | // pcfContextService now provides ajax and data functions. 9 | const pcfContextService = new PcfContextService({ context: props.context, instanceid: props.instanceid, updatePrimaryProperty: props.updatePrimaryProperty }); 10 | 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | }; 21 | 22 | export default PortalFilesApp; 23 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/components/HeaderButtons.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Button } from "@fluentui/react-components"; 3 | import { getTranslation, LanguageCode, Message } from "../utils/localization"; 4 | 5 | export interface IHeaderButtonsProps { 6 | selectedCount: number; 7 | uploadingCount: number; 8 | onDelete: () => void; 9 | onCancel: () => void; 10 | onToggleCollapse: () => void; 11 | language: LanguageCode; // Added language prop 12 | } 13 | 14 | export const HeaderButtons = (props: IHeaderButtonsProps): JSX.Element => { 15 | return ( 16 |
17 | 25 | 33 | 40 |
41 | ); 42 | }; 43 | 44 | export default HeaderButtons; 45 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/hooks/useAnnotations.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useCallback } from "react"; 2 | import { IAnnotation } from "../types"; 3 | import { usePcfContext } from "../services/PcfContext"; 4 | import { annotationService } from "../services/AnnotationService"; 5 | 6 | export function useAnnotations() { 7 | const pcfContext = usePcfContext(); 8 | const [annotations, setAnnotations] = useState([]); 9 | const [error, setError] = useState(""); 10 | 11 | const refreshAnnotations = useCallback(() => { 12 | annotationService 13 | .loadAnnotations(pcfContext.getEntityTypeName(), pcfContext.getEntityId()) 14 | .then((result) => { 15 | let updatedAnnotations = result as IAnnotation[]; 16 | if (!pcfContext.displayAllFiles) { 17 | updatedAnnotations = updatedAnnotations.map(annotation => ({ 18 | ...annotation, 19 | display: false 20 | })); 21 | } 22 | setAnnotations(updatedAnnotations); 23 | return updatedAnnotations; 24 | }) 25 | .catch(() => setError("Failed to load files")); 26 | }, []); 27 | 28 | useEffect(() => { 29 | refreshAnnotations(); 30 | }, [refreshAnnotations]); 31 | 32 | // Watch for changes in the annotations state and update the primary property 33 | useEffect(() => { 34 | pcfContext.updatePrimaryProperty( 35 | annotations.length > 0 ? annotations.length.toString() : undefined 36 | ); 37 | }, [annotations]); 38 | 39 | return { annotations, error, refreshAnnotations, setAnnotations, setError }; 40 | } 41 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/hooks/useWindowSize.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | export function useWindowSize() { 4 | const [windowSize, setWindowSize] = useState<{ width: number; height: number }>({ 5 | width: window.innerWidth, 6 | height: window.innerHeight 7 | }); 8 | 9 | useEffect(() => { 10 | const handleResize = () => { 11 | setWindowSize({ width: window.innerWidth, height: window.innerHeight }); 12 | }; 13 | window.addEventListener("resize", handleResize); 14 | return () => window.removeEventListener("resize", handleResize); 15 | }, []); 16 | 17 | return windowSize; 18 | } 19 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/services/PcfContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { PcfContextService } from './PcfContextService' 3 | 4 | interface PcfContextProviderProps { 5 | pcfcontext: PcfContextService, 6 | children: React.ReactNode 7 | } 8 | 9 | const PcfContext = React.createContext(undefined!) 10 | 11 | export const PcfContextProvider = ({ pcfcontext, children }: PcfContextProviderProps) => { 12 | return ( 13 | 14 | {children} 15 | 16 | ) 17 | } 18 | 19 | export const usePcfContext = () => { 20 | return React.useContext(PcfContext) 21 | } 22 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/types/Annotations.ts: -------------------------------------------------------------------------------- 1 | export interface IAnnotation { 2 | annotationid: string; 3 | filename: string; 4 | createdon: string; 5 | filesize?: number; // NEW property in bytes (optional) 6 | display?: boolean; // NEW property to control visibility (optional) 7 | objectid?: string; 8 | objecttypecode?: string; 9 | } 10 | 11 | export interface IAnnotationsResponse { 12 | value: IAnnotation[]; 13 | } 14 | 15 | export interface FileUploadOptions { 16 | onProgress?: (percent: number) => void; 17 | abortSignal?: AbortSignal; 18 | } -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Annotations"; 2 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/utils/constants.ts: -------------------------------------------------------------------------------- 1 | export const AZURE_FILE_EXTENSION = ".azure.txt"; 2 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/utils/formatDate.ts: -------------------------------------------------------------------------------- 1 | export function formatDate(dateString: string): string { 2 | const date = new Date(dateString); 3 | const year = date.getFullYear(); 4 | const month = String(date.getMonth() + 1).padStart(2, '0'); 5 | const day = String(date.getDate()).padStart(2, '0'); 6 | const hours = String(date.getHours()).padStart(2, '0'); 7 | const minutes = String(date.getMinutes()).padStart(2, '0'); 8 | return `${year}:${month}:${day} - ${hours}:${minutes}`; 9 | } 10 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./formatDate"; 2 | export * from "./themeGenerator"; 3 | export * from "./constants"; 4 | export * from "./localization"; 5 | export * from "./layouts"; 6 | -------------------------------------------------------------------------------- /PowerPagesFileManager/PowerPagesFileManager/utils/layouts.ts: -------------------------------------------------------------------------------- 1 | export enum Layout { 2 | Horizontal = "Horizontal", 3 | Vertical = "Vertical" 4 | } 5 | 6 | export function getLayout(rawLayout: string): Layout { 7 | // Mapping raw values to a Layout enum; defaults to Vertical 8 | const layoutMap: Record = { 9 | "0": Layout.Vertical, 10 | "1": Layout.Horizontal, 11 | "Vertical": Layout.Vertical, 12 | "Horizontal": Layout.Horizontal 13 | }; 14 | return layoutMap[rawLayout] || Layout.Vertical; 15 | } 16 | -------------------------------------------------------------------------------- /PowerPagesFileManager/Solution/PowerPagesFileManagerSolution/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj 6 | 7 | # MSBuild Binary and Structured Log 8 | *.binlog 9 | -------------------------------------------------------------------------------- /PowerPagesFileManager/Solution/PowerPagesFileManagerSolution/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /PowerPagesFileManager/Solution/PowerPagesFileManagerSolution/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /PowerPagesFileManager/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import eslintjs from "@eslint/js"; 2 | import microsoftPowerApps from "@microsoft/eslint-plugin-power-apps"; 3 | import pluginPromise from "eslint-plugin-promise"; 4 | import globals from "globals"; 5 | import typescriptEslint from "typescript-eslint"; 6 | 7 | /** @type {import('eslint').Linter.Config[]} */ 8 | export default [ 9 | { 10 | ignores: ["**/generated/"], 11 | }, 12 | eslintjs.configs.recommended, 13 | ...typescriptEslint.configs.recommended, 14 | ...typescriptEslint.configs.stylistic, 15 | pluginPromise.configs["flat/recommended"], 16 | microsoftPowerApps.configs.paCheckerHosted, 17 | { 18 | plugins: { 19 | "@microsoft/power-apps": microsoftPowerApps, 20 | }, 21 | 22 | languageOptions: { 23 | globals: { 24 | ...globals.browser, 25 | ComponentFramework: true, 26 | }, 27 | parserOptions: { 28 | ecmaVersion: 2020, 29 | sourceType: "module", 30 | projectService: true, 31 | tsconfigRootDir: import.meta.dirname, 32 | }, 33 | }, 34 | 35 | rules: { 36 | "@typescript-eslint/no-unused-vars": "off", 37 | }, 38 | }, 39 | ]; 40 | -------------------------------------------------------------------------------- /PowerPagesFileManager/images/PowerPagesFileManager.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/PowerPagesFileManager/images/PowerPagesFileManager.gif -------------------------------------------------------------------------------- /PowerPagesFileManager/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@fluentui/react-components": "^9.59.0", 17 | "@types/chroma-js": "^3.1.1", 18 | "@types/jquery": "^3.5.32", 19 | "axios": "^1.8.1", 20 | "chroma-js": "^3.1.2", 21 | "react": "^18.0.0", 22 | "react-dom": "^18.0.0", 23 | "uuid": "^11.1.0" 24 | }, 25 | "devDependencies": { 26 | "@eslint/js": "^9.17.0", 27 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 28 | "@types/node": "^18.19.54", 29 | "@types/powerapps-component-framework": "^1.3.15", 30 | "eslint-plugin-promise": "^7.1.0", 31 | "globals": "15.13.0", 32 | "pcf-scripts": "^1", 33 | "pcf-start": "^1", 34 | "typescript": "^4.9.5", 35 | "typescript-eslint": "^8.18.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /PowerPagesFileManager/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /PowerPagesFileManager/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | "module": "es2015", 6 | "moduleResolution": "node" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /RestrictedChoice/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj 15 | 16 | # MSBuild Binary and Structured Log 17 | *.binlog 18 | 19 | # Visual Studio cache/options directory 20 | /.vs 21 | 22 | # macos 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /RestrictedChoice/RestrictedChoice/RestrictedChoiceApp.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { IdPrefixProvider, FluentProvider} from "@fluentui/react-components"; 3 | import { PcfContextProvider } from "./services/PcfContext"; 4 | import { PcfContextService, IPcfContextServiceProps } from "./services/PcfContextService"; 5 | import { RestrictedChoiceControl } from "./components/RestrictedChoice"; 6 | import { useStyles } from "./utils/styles"; 7 | 8 | // Extend the props interface to include both PCF context and control props. 9 | export interface IRestrictedChoiceAppProps extends IPcfContextServiceProps { 10 | onChange: (newValue: number | number[] | null) => void; 11 | // These props are passed from index.ts 12 | options: ComponentFramework.PropertyHelper.OptionMetadata[]; 13 | restrictedOptions: number[]; 14 | restrictedChoiceVisibility: number; // 1 for Disabled, 0 for Hide 15 | currentValue: number | number[] | null; 16 | restrictChoices: boolean; 17 | isMultiSelect: boolean; 18 | defaultValue?: number | number[] | null; 19 | } 20 | 21 | export const RestrictedChoiceApp: React.FC = (props) => { 22 | const styles = useStyles(); 23 | // Create the context service. 24 | const pcfContextService = new PcfContextService({ context: props.context, instanceid: props.instanceid }); 25 | 26 | return ( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ); 35 | }; 36 | 37 | export default RestrictedChoiceApp; -------------------------------------------------------------------------------- /RestrictedChoice/RestrictedChoice/services/PcfContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { PcfContextService } from './PcfContextService' 3 | 4 | interface PcfContextProviderProps { 5 | pcfcontext: PcfContextService, 6 | children: React.ReactNode 7 | } 8 | 9 | const PcfContext = React.createContext(undefined!) 10 | 11 | export const PcfContextProvider = ({ pcfcontext, children }: PcfContextProviderProps) => { 12 | return ( 13 | 14 | {children} 15 | 16 | ) 17 | } 18 | 19 | export const usePcfContext = () => { 20 | return React.useContext(PcfContext) 21 | } 22 | -------------------------------------------------------------------------------- /RestrictedChoice/RestrictedChoice/utils/styles.ts: -------------------------------------------------------------------------------- 1 | import { makeStyles } from "@fluentui/react-components"; 2 | 3 | export const useStyles = makeStyles({ 4 | root: { 5 | width: "100%", 6 | }, 7 | }); -------------------------------------------------------------------------------- /RestrictedChoice/Solution/RestrictedChoiceControl/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj 6 | 7 | # MSBuild Binary and Structured Log 8 | *.binlog 9 | -------------------------------------------------------------------------------- /RestrictedChoice/Solution/RestrictedChoiceControl/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /RestrictedChoice/Solution/RestrictedChoiceControl/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /RestrictedChoice/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import eslintjs from "@eslint/js"; 2 | import microsoftPowerApps from "@microsoft/eslint-plugin-power-apps"; 3 | import pluginPromise from "eslint-plugin-promise"; 4 | import reactPlugin from "eslint-plugin-react"; 5 | import globals from "globals"; 6 | import typescriptEslint from "typescript-eslint"; 7 | 8 | /** @type {import('eslint').Linter.Config[]} */ 9 | export default [ 10 | { 11 | ignores: ["**/generated"], 12 | }, 13 | eslintjs.configs.recommended, 14 | ...typescriptEslint.configs.recommendedTypeChecked, 15 | ...typescriptEslint.configs.stylisticTypeChecked, 16 | pluginPromise.configs["flat/recommended"], 17 | microsoftPowerApps.configs.paCheckerHosted, 18 | reactPlugin.configs.flat.recommended, 19 | { 20 | plugins: { 21 | "@microsoft/power-apps": microsoftPowerApps, 22 | }, 23 | 24 | languageOptions: { 25 | globals: { 26 | ...globals.browser, 27 | ComponentFramework: true, 28 | }, 29 | parserOptions: { 30 | ecmaVersion: 2020, 31 | sourceType: "module", 32 | projectService: true, 33 | tsconfigRootDir: import.meta.dirname, 34 | }, 35 | }, 36 | 37 | rules: { 38 | "@typescript-eslint/no-unused-vars": "off", 39 | }, 40 | settings: { 41 | react: { 42 | version: "detect", 43 | }, 44 | }, 45 | }, 46 | ]; 47 | -------------------------------------------------------------------------------- /RestrictedChoice/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "pcfAllowCustomWebpack": "on" 3 | } -------------------------------------------------------------------------------- /RestrictedChoice/images/2025-03-07_15-36-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RestrictedChoice/images/2025-03-07_15-36-00.png -------------------------------------------------------------------------------- /RestrictedChoice/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@fluentui/react-components": "9.46.2", 17 | "react": "16.14.0", 18 | "react-dom": "16.14.0", 19 | "uuidv4": "^6.2.13" 20 | }, 21 | "devDependencies": { 22 | "@eslint/js": "^9.17.0", 23 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 24 | "@types/powerapps-component-framework": "^1.3.15", 25 | "@types/react": "^16.14.60", 26 | "@types/react-dom": "^16.9.24", 27 | "clean-webpack-plugin": "^4.0.0", 28 | "eslint-plugin-promise": "^7.1.0", 29 | "eslint-plugin-react": "^7.37.2", 30 | "globals": "^15.13.0", 31 | "pcf-scripts": "^1", 32 | "pcf-start": "^1", 33 | "react": "^16.14.0", 34 | "speed-measure-webpack-plugin": "^1.5.0", 35 | "typescript": "^4.9.5", 36 | "typescript-eslint": "^8.18.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /RestrictedChoice/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /RestrictedChoice/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | "module": "es2015", 6 | "moduleResolution": "node" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /RestrictedChoice/webpack.config.js: -------------------------------------------------------------------------------- 1 | const SpeedMeasurePlugin = require("speed-measure-webpack-plugin"); 2 | const smp = new SpeedMeasurePlugin(); 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 4 | 5 | module.exports = smp.wrap({ 6 | devtool: 'source-map', 7 | plugins: [ 8 | // will clean the build folder on successful build 9 | new CleanWebpackPlugin(), 10 | ] 11 | }); -------------------------------------------------------------------------------- /RotationalImage/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /RotationalImage/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /RotationalImage/Solution/RotationalImageComponent/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /RotationalImage/Solution/RotationalImageComponent/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /RotationalImage/Solution/RotationalImageComponent/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /RotationalImage/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /RotationalImage/images/AddComponentToForm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RotationalImage/images/AddComponentToForm.png -------------------------------------------------------------------------------- /RotationalImage/images/ComponentProperties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RotationalImage/images/ComponentProperties.png -------------------------------------------------------------------------------- /RotationalImage/images/ConverImageToBase64.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RotationalImage/images/ConverImageToBase64.gif -------------------------------------------------------------------------------- /RotationalImage/images/ImportComponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RotationalImage/images/ImportComponent.png -------------------------------------------------------------------------------- /RotationalImage/images/ImportComponentRibbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RotationalImage/images/ImportComponentRibbon.png -------------------------------------------------------------------------------- /RotationalImage/images/RotationalImage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RotationalImage/images/RotationalImage.gif -------------------------------------------------------------------------------- /RotationalImage/images/RunOnStart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RotationalImage/images/RunOnStart.png -------------------------------------------------------------------------------- /RotationalImage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/node": "^10.12.18", 17 | "hex-and-rgba": "^1.4.2", 18 | "react": "^16.13.1", 19 | "react-dom": "^16.13.1" 20 | }, 21 | "devDependencies": { 22 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 23 | "@types/powerapps-component-framework": "^1.3", 24 | "@types/react-dom": "^16", 25 | "@typescript-eslint/eslint-plugin": "^8.18.0", 26 | "@typescript-eslint/parser": "^8.18.0", 27 | "eslint": "^8.57.0", 28 | "eslint-plugin-import": "^2.31.0", 29 | "eslint-plugin-node": "^11.1.0", 30 | "eslint-plugin-promise": "^7.1.0", 31 | "pcf-scripts": "^1", 32 | "pcf-start": "^1", 33 | "typescript": "^4.9.5" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /RotationalImage/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /RotationalImage/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /RuntimeInfo/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off", 25 | "@typescript-eslint/no-empty-object-type": "off" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /RuntimeInfo/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /RuntimeInfo/RuntimeInfo/browser-info.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'browser-info'; -------------------------------------------------------------------------------- /RuntimeInfo/Solution/RuntimeInfoComponent/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /RuntimeInfo/Solution/RuntimeInfoComponent/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /RuntimeInfo/Solution/RuntimeInfoComponent/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /RuntimeInfo/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /RuntimeInfo/images/EditComponentName.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/EditComponentName.png -------------------------------------------------------------------------------- /RuntimeInfo/images/EditComponentNameUpdateName.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/EditComponentNameUpdateName.png -------------------------------------------------------------------------------- /RuntimeInfo/images/ImportComponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/ImportComponent.png -------------------------------------------------------------------------------- /RuntimeInfo/images/ImportComponentFromCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/ImportComponentFromCode.png -------------------------------------------------------------------------------- /RuntimeInfo/images/RunTimeInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/RunTimeInfo.png -------------------------------------------------------------------------------- /RuntimeInfo/images/RuntimeInfoDesktopFirefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/RuntimeInfoDesktopFirefox.png -------------------------------------------------------------------------------- /RuntimeInfo/images/RuntimeInfoPhone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/RuntimeInfoPhone.png -------------------------------------------------------------------------------- /RuntimeInfo/images/UtilizePropertyInTextField.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/RuntimeInfo/images/UtilizePropertyInTextField.png -------------------------------------------------------------------------------- /RuntimeInfo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/node": "^18.19", 17 | "@types/ua-parser-js": "^0.7.33", 18 | "ua-parser-js": "^0.7.28" 19 | }, 20 | "devDependencies": { 21 | "@types/powerapps-component-framework": "^1.3", 22 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 23 | "@typescript-eslint/eslint-plugin": "^8.18.0", 24 | "@typescript-eslint/parser": "^8.18.0", 25 | "eslint": "^8.57.0", 26 | "eslint-plugin-import": "^2.31.0", 27 | "eslint-plugin-node": "^11.1.0", 28 | "eslint-plugin-promise": "^7.1.0", 29 | "pcf-scripts": "^1", 30 | "pcf-start": "^1", 31 | "typescript": "^4.9.5" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /RuntimeInfo/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /RuntimeInfo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /Scheduler/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj 15 | 16 | # MSBuild Binary and Structured Log 17 | *.binlog 18 | 19 | # Visual Studio cache/options directory 20 | /.vs 21 | 22 | # macos 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /Scheduler/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "github.copilot.chat.codeGeneration.useInstructionFiles": true, 3 | "chat.instructionsFilesLocations": { 4 | ".github": true 5 | }, 6 | } -------------------------------------------------------------------------------- /Scheduler/Sample/RAW! Scheduler Sample.msapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Scheduler/Sample/RAW! Scheduler Sample.msapp -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/eventClicked.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData, EventItem } from "react-big-schedule"; // adjust import paths as needed 2 | 3 | export function createEventClickedCallback( 4 | onClickSelectedRecord: (eventId: string) => void 5 | ) { 6 | return (schedulerData: SchedulerData, event: EventItem) => { 7 | const eventId = event.id as string; 8 | if (eventId) { 9 | onClickSelectedRecord?.(eventId); 10 | } 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/index.ts: -------------------------------------------------------------------------------- 1 | export {createEventClickedCallback} from "./eventClicked"; 2 | export {createSlotClickedFuncCallback} from "./slotClickedFunc"; 3 | export {createNewEventCallback} from "./newEvent"; 4 | export {createToggleExpandFuncCallback} from "./toggleExpandFunc"; 5 | export {createNextClickCallback} from "./nextClick"; 6 | export {createPrevClickCallback} from "./prevClick"; 7 | export {createOnViewChangeCallback} from "./onViewChange"; -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/newEvent.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData, EventItem } from "react-big-schedule"; 2 | 3 | export function createNewEventCallback( 4 | onNewEvent: (slotId: string, start: Date, end: Date) => void 5 | ) { 6 | return ( 7 | schedulerData: SchedulerData, 8 | slotId: string, 9 | slotName: string, 10 | start: string | Date, 11 | end: string | Date, 12 | type: string, 13 | item: EventItem 14 | ) => { 15 | let startDate = start; 16 | let endDate = end; 17 | if (typeof start === "string") { 18 | startDate = new Date(start); 19 | } 20 | if (typeof end === "string") { 21 | endDate = new Date(end); 22 | } 23 | if (onNewEvent) { 24 | onNewEvent( 25 | slotId, 26 | startDate as Date, 27 | endDate as Date 28 | ); 29 | } 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/nextClick.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData } from "react-big-schedule"; 2 | import { SchedulerAction, Event } from "../../types"; 3 | 4 | export function createNextClickCallback( 5 | events: Event[], 6 | schedulerView: string, 7 | dispatch: (action: SchedulerAction) => void, 8 | onDateChange: (start: Date, viewStart: Date, viewEnd: Date, view: string) => void 9 | ) { 10 | return (schedulerData: SchedulerData) => { 11 | schedulerData.next(); 12 | schedulerData.setEvents(events); 13 | dispatch({ type: "UPDATE_SCHEDULER", payload: schedulerData }); 14 | onDateChange?.( 15 | schedulerData.getViewStartDate().toDate(), 16 | schedulerData.getViewStartDate().toDate(), 17 | schedulerData.getViewEndDate().toDate(), 18 | schedulerView 19 | ); 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/onViewChange.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData } from "react-big-schedule"; 2 | import { View } from "../../types"; 3 | 4 | export function createOnViewChangeCallback( 5 | availableViews: View[], 6 | setSchedulerView: (viewName: string) => void 7 | ) { 8 | return (schedulerData: SchedulerData, view: View) => { 9 | const foundView = availableViews.find(v => v.viewType === view.viewType); 10 | if (foundView) { 11 | setSchedulerView(foundView.name); 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/prevClick.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData } from "react-big-schedule"; 2 | import { SchedulerAction, Event} from "../../types"; 3 | 4 | export function createPrevClickCallback( 5 | events: Event[], 6 | schedulerView: string, 7 | dispatch: (action: SchedulerAction) => void, 8 | onDateChange: (start: Date, viewStart: Date, viewEnd: Date, view: string) => void 9 | ) { 10 | return (schedulerData: SchedulerData) => { 11 | schedulerData.prev(); 12 | schedulerData.setEvents(events); 13 | dispatch({ type: "UPDATE_SCHEDULER", payload: schedulerData }); 14 | onDateChange?.( 15 | schedulerData.getViewStartDate().toDate(), 16 | schedulerData.getViewStartDate().toDate(), 17 | schedulerData.getViewEndDate().toDate(), 18 | schedulerView 19 | ); 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/slotClickedFunc.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData, EventItem, ResourceEvent } from "react-big-schedule"; 2 | import { Slot } from "../../types"; 3 | 4 | export function createSlotClickedFuncCallback( 5 | onClickSelectedSlot: (resourceId: string) => void 6 | ) { 7 | return (schedulerData: SchedulerData, slot: ResourceEvent) => { 8 | const slotExtended = slot as Slot 9 | if (slotExtended && slotExtended.slotId) { 10 | const resourceId = slotExtended.slotId; 11 | onClickSelectedSlot(resourceId); 12 | } 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/callbacks/toggleExpandFunc.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData } from "react-big-schedule"; 2 | import { SchedulerAction } from "../../types"; 3 | 4 | export function createToggleExpandFuncCallback( 5 | dispatch: (action: SchedulerAction) => void 6 | ) { 7 | return (schedulerData: SchedulerData, slotId: string) => { 8 | schedulerData.toggleExpandStatus(slotId); 9 | dispatch({ type: "UPDATE_SCHEDULER", payload: schedulerData }); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/renderers/eventItemTemplateResolver.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { SchedulerData, EventItem } from "react-big-schedule"; 3 | import Color from "color"; 4 | 5 | export function eventItemTemplateResolver( 6 | schedulerData: SchedulerData, 7 | event: EventItem, 8 | bgColor: string, 9 | isStart: boolean, 10 | isEnd: boolean, 11 | mustAddCssClass: string, 12 | mustBeHeight: number, 13 | agendaMaxEventWidth: number 14 | ): React.ReactNode { 15 | const additionalClass = 'round-all'; 16 | 17 | // Use Color to determine if background is dark or light 18 | let textColor = "#000"; 19 | try { 20 | if (Color(bgColor).isDark()) { 21 | textColor = "#fff"; 22 | } 23 | } catch { 24 | // fallback if color parsing fails 25 | textColor = "#000"; 26 | } 27 | 28 | return ( 29 |
35 | {event.title} 36 |
37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/renderers/index.ts: -------------------------------------------------------------------------------- 1 | export {eventItemPopoverTemplateResolver} from "./eventItemPopoverTemplateResolver"; 2 | export {eventItemTemplateResolver} from "./eventItemTemplateResolver"; 3 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/components/schedulerWrapper.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Scheduler, SchedulerProps, EventItem } from "react-big-schedule"; 3 | 4 | // Cast Scheduler to ComponentType for JSX compatibility 5 | const SchedulerWrapper: React.ComponentType> = Scheduler as unknown as React.ComponentType>; 6 | 7 | export default SchedulerWrapper; -------------------------------------------------------------------------------- /Scheduler/Scheduler/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useAvailableViews } from "./useAvailableViews"; 2 | export { useShowHeader } from "./useShowHeader"; 3 | export { useSchedulerView } from "./useSchedulerView"; 4 | export { useSchedulerDate } from "./useSchedulerDate"; 5 | export { useSchedulerLanguage } from "./useSchedulerLanguage"; 6 | export { useResourceNameHeader } from "./useResourceNameHeader"; 7 | export { useWorkWeekDays } from "./useWorkWeekDays"; 8 | export {useDisplayWeekend} from "./useDisplayWeekend"; 9 | export {useNonWorkingTimeColors} from "./useNonWorkingTimeColors"; 10 | export {useDayViewOptions} from "./useDayViewOptions"; -------------------------------------------------------------------------------- /Scheduler/Scheduler/hooks/useDisplayWeekend.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { SchedulerData } from "react-big-schedule"; 3 | import { PcfContextService } from "../services/pcfContextService"; 4 | import { SchedulerAction } from "../types"; 5 | 6 | /** 7 | * Hook to get the value of the schedulerDisplayWeekend property from PCF context. 8 | * Returns true if weekends should be displayed, false otherwise. 9 | * Defaults to true if the property is not set. 10 | */ 11 | export function useDisplayWeekend( 12 | pcfContext: PcfContextService, 13 | schedulerData: SchedulerData | null, 14 | dispatch: (action: SchedulerAction) => void 15 | ): boolean { 16 | const getValue = () => { 17 | return pcfContext.context.parameters?.schedulerDisplayWeekend?.raw || true; 18 | }; 19 | 20 | const [displayWeekend, setDisplayWeekend] = useState(getValue); 21 | 22 | useEffect(() => { 23 | setDisplayWeekend(getValue()); 24 | }, [pcfContext.context.parameters.schedulerDisplayWeekend?.raw]); 25 | 26 | // Effect to update the scheduler config when displayWeekend changes 27 | useEffect(() => { 28 | if (schedulerData && schedulerData.config) { 29 | schedulerData.config.displayWeekend = displayWeekend; 30 | if (dispatch) { 31 | dispatch({ type: "UPDATE_SCHEDULER", payload: schedulerData }); 32 | } 33 | } 34 | }, [displayWeekend]); 35 | 36 | return displayWeekend; 37 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/hooks/useResourceNameHeader.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { SchedulerData } from "react-big-schedule"; 3 | import { getLocalizedResourceName } from "../utils/localization"; 4 | import { PcfContextService } from "../services/pcfContextService"; 5 | import { SchedulerAction } from "../types"; 6 | 7 | export function useResourceNameHeader( 8 | pcfContext: PcfContextService, 9 | state: { schedulerData: SchedulerData | null }, 10 | dispatch: (action: SchedulerAction) => void 11 | ): string { 12 | const getHeader = () => { 13 | const param = pcfContext.context.parameters.resourceNameHeader?.raw?.trim(); 14 | if (param) return param; 15 | const lang = state.schedulerData?.localeDayjs().locale() || "en"; 16 | return getLocalizedResourceName(lang); 17 | }; 18 | 19 | const [resourceNameHeader, setResourceNameHeader] = useState(getHeader); 20 | 21 | useEffect(() => { 22 | setResourceNameHeader(getHeader()); 23 | }, [ 24 | pcfContext.context.parameters.resourceNameHeader?.raw, 25 | state.schedulerData?.localeDayjs().locale() 26 | ]); 27 | 28 | useEffect(() => { 29 | if (state.schedulerData) { 30 | state.schedulerData.config.resourceName = resourceNameHeader; 31 | dispatch({ type: "UPDATE_SCHEDULER", payload: state.schedulerData }); 32 | } 33 | }, [resourceNameHeader]); 34 | 35 | return resourceNameHeader; 36 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/hooks/useShowHeader.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { SchedulerData } from "react-big-schedule"; 3 | import { PcfContextService } from "../services/pcfContextService"; 4 | import { SchedulerAction } from "../types"; 5 | 6 | export function useShowHeader( 7 | pcfContext: PcfContextService, 8 | state: { schedulerData: SchedulerData | null }, 9 | dispatch: (action: SchedulerAction) => void 10 | ): boolean { 11 | const [showHeader, setShowHeader] = useState( 12 | pcfContext.context.parameters.showSchedulerHeader?.raw !== false 13 | ); 14 | 15 | // Sync showHeader with parameter changes 16 | useEffect(() => { 17 | setShowHeader(pcfContext.context.parameters.showSchedulerHeader?.raw !== false); 18 | }, [pcfContext.context.parameters.showSchedulerHeader?.raw]); 19 | 20 | // Update SchedulerData and dispatch when showHeader changes 21 | useEffect(() => { 22 | if (state.schedulerData) { 23 | state.schedulerData.config.headerEnabled = showHeader; 24 | dispatch({ type: "UPDATE_SCHEDULER", payload: state.schedulerData }); 25 | } 26 | }, [showHeader]); 27 | 28 | return showHeader; 29 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/mocks/MockPCFClient.ts: -------------------------------------------------------------------------------- 1 | export interface MockPCFClientOptions { 2 | disableScroll?: boolean; 3 | formFactor?: number; 4 | client?: string; 5 | offline?: boolean; 6 | networkAvailable?: boolean; 7 | } 8 | 9 | export class MockPCFClient implements ComponentFramework.Client { 10 | disableScroll: boolean; 11 | private formFactor: number; 12 | private client: string; 13 | private offline: boolean; 14 | private networkAvailable: boolean; 15 | 16 | constructor(options: MockPCFClientOptions = {}) { 17 | this.disableScroll = options.disableScroll ?? false; 18 | this.formFactor = options.formFactor ?? 1; 19 | this.client = options.client ?? "Web"; 20 | this.offline = options.offline ?? false; 21 | this.networkAvailable = options.networkAvailable ?? true; 22 | } 23 | 24 | getFormFactor(): number { 25 | return this.formFactor; 26 | } 27 | 28 | getClient(): string { 29 | return this.client; 30 | } 31 | 32 | isOffline(): boolean { 33 | return this.offline; 34 | } 35 | 36 | isNetworkAvailable(): boolean { 37 | return this.networkAvailable; 38 | } 39 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/mocks/MockPCFFactory.ts: -------------------------------------------------------------------------------- 1 | export interface MockPCFFactoryOptions { 2 | getPopupService?: () => ComponentFramework.FactoryApi.Popup.PopupService; 3 | requestRender?: () => void; 4 | } 5 | 6 | export class MockPCFFactory implements ComponentFramework.Factory { 7 | private _getPopupService?: () => ComponentFramework.FactoryApi.Popup.PopupService; 8 | private _requestRender?: () => void; 9 | 10 | constructor(options: MockPCFFactoryOptions = {}) { 11 | this._getPopupService = options.getPopupService; 12 | this._requestRender = options.requestRender; 13 | } 14 | 15 | getPopupService(): ComponentFramework.FactoryApi.Popup.PopupService { 16 | if (this._getPopupService) { 17 | return this._getPopupService(); 18 | } 19 | throw new Error("Method not implemented."); 20 | } 21 | 22 | requestRender(): void { 23 | if (this._requestRender) { 24 | this._requestRender(); 25 | return; 26 | } 27 | throw new Error("Method not implemented."); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/mocks/MockPCFMode.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | export interface MockPCFModeOptions { 3 | allocatedHeight?: number; 4 | allocatedWidth?: number; 5 | isControlDisabled?: boolean; 6 | isVisible?: boolean; 7 | label?: string; 8 | contextInfo?: { 9 | entityId?: string; 10 | entityTypeName?: string; 11 | entityRecordName?: string; 12 | [key: string]: any; 13 | }; 14 | } 15 | 16 | export class MockPCFMode implements ComponentFramework.Mode { 17 | allocatedHeight: number; 18 | allocatedWidth: number; 19 | isControlDisabled: boolean; 20 | isVisible: boolean; 21 | label: string; 22 | // Add contextInfo property for custom context usage 23 | contextInfo?: { 24 | entityId?: string; 25 | entityTypeName?: string; 26 | entityRecordName?: string; 27 | [key: string]: any; 28 | }; 29 | 30 | constructor(options: MockPCFModeOptions = {}) { 31 | this.allocatedHeight = options.allocatedHeight ?? 600; 32 | this.allocatedWidth = options.allocatedWidth ?? 800; 33 | this.isControlDisabled = options.isControlDisabled ?? false; 34 | this.isVisible = options.isVisible ?? true; 35 | this.label = options.label ?? "Mock Mode"; 36 | this.contextInfo = options.contextInfo; 37 | } 38 | 39 | setControlState(state: ComponentFramework.Dictionary): boolean { 40 | throw new Error("Method not implemented."); 41 | } 42 | setFullScreen(value: boolean): void { 43 | throw new Error("Method not implemented."); 44 | } 45 | trackContainerResize(value: boolean): void { 46 | throw new Error("Method not implemented."); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/mocks/MockPCFParameters.ts: -------------------------------------------------------------------------------- 1 | import { MockPCFDataSet } from "./MockPCFDataSet"; 2 | 3 | /** 4 | * MockPCFParameterValue represents the structure of a PCF parameter value. 5 | */ 6 | export type MockPCFParameterValue = { 7 | raw: T; 8 | formatted?: string; 9 | [key: string]: any; 10 | }; 11 | 12 | /** 13 | * MockPCFParameters provides a generic, flexible way to mock PCF context parameters. 14 | * Supports both params.getParameter("key") and params.key access. 15 | */ 16 | export class MockPCFParameters { 17 | [key: string]: MockPCFParameterValue | any; 18 | 19 | constructor(initialParams?: Record) { 20 | if (initialParams) { 21 | for (const key of Object.keys(initialParams)) { 22 | this[key] = initialParams[key]; 23 | } 24 | } 25 | } 26 | 27 | /** 28 | * Set a parameter value. 29 | */ 30 | setParameter(key: string, value: MockPCFParameterValue) { 31 | this[key] = value; 32 | } 33 | 34 | /** 35 | * Get a parameter value. 36 | */ 37 | getParameter(key: string): MockPCFParameterValue { 38 | return this[key]; 39 | } 40 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/mocks/MockPCFResources.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | export interface MockPCFResourcesOptions { 3 | getResource?: (id: string, success: (data: string) => void, failure: () => void) => void; 4 | getString?: (id: string) => string; 5 | } 6 | 7 | export class MockPCFResources implements ComponentFramework.Resources { 8 | private _getResource?: (id: string, success: (data: string) => void, failure: () => void) => void; 9 | private _getString?: (id: string) => string; 10 | 11 | constructor(options: MockPCFResourcesOptions = {}) { 12 | this._getResource = options.getResource; 13 | this._getString = options.getString; 14 | } 15 | 16 | getResource(id: string, success: (data: string) => void, failure: () => void): void { 17 | if (this._getResource) { 18 | this._getResource(id, success, failure); 19 | } else { 20 | throw new Error("Method not implemented."); 21 | } 22 | } 23 | 24 | getString(id: string): string { 25 | if (this._getString) { 26 | return this._getString(id); 27 | } 28 | throw new Error("Method not implemented."); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/mocks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "."; 2 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/resources/schedulerOverrides.css: -------------------------------------------------------------------------------- 1 | /* Scheduler Components */ 2 | .react-big-schedule { 3 | margin: 0px auto !important; 4 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/schedulerApp.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { PcfContextProvider } from "./services/pcfContext"; 3 | import { PcfContextService } from "./services/pcfContextService"; 4 | import SchedulerControl from "./components/scheduler"; 5 | import { DndProvider } from 'react-dnd'; 6 | import { HTML5Backend } from 'react-dnd-html5-backend'; 7 | import { ISchedulerControlProps } from "./types/schedulerTypes"; 8 | 9 | export const SchedulerApp: React.FC = (props) => { 10 | // Create the context service. 11 | const pcfContextService = new PcfContextService({ 12 | context: props.context, 13 | instanceid: props.instanceid, 14 | height: props.height 15 | }); 16 | 17 | // Wrap the SchedulerControl in providers for drag-and-drop and PCF context. 18 | return ( 19 | 20 | 21 | 24 | 25 | 26 | ); 27 | }; 28 | 29 | export default SchedulerApp; -------------------------------------------------------------------------------- /Scheduler/Scheduler/services/metadataService.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import axios, { AxiosResponse } from "axios"; 4 | import { IInputs } from "../generated/ManifestTypes"; 5 | 6 | export const getEntities = async ( 7 | baseUrl: string, 8 | ): Promise<{ displayName: string; logicalName: string }[]> => { 9 | const filter = 10 | "IsValidForAdvancedFind%20eq%20true%20and%20IsCustomizable/Value%20eq%20true"; 11 | const url = `${baseUrl}/api/data/v9.1/EntityDefinitions?$select=LogicalName,DisplayName&$filter=${filter}`; 12 | 13 | try { 14 | const response: AxiosResponse = await axios.get(url, { 15 | headers: { 16 | "OData-MaxVersion": "4.0", 17 | "OData-Version": "4.0", 18 | Accept: "application/json", 19 | "Content-Type": "application/json; charset=utf-8", 20 | }, 21 | }); 22 | 23 | const result = response.data; 24 | if (result.status < 0) { 25 | throw new Error(result.statusText); 26 | } 27 | 28 | return result.value.map( 29 | (entity: { 30 | DisplayName: { UserLocalizedLabel: { Label: string } }; 31 | LogicalName: string; 32 | }) => ({ 33 | displayName: 34 | entity.DisplayName?.UserLocalizedLabel?.Label || entity.LogicalName, 35 | logicalName: entity.LogicalName, 36 | }) 37 | ); 38 | } catch (error) { 39 | if (axios.isAxiosError(error)) { 40 | throw new Error(error.response?.statusText ?? error.message); 41 | } else { 42 | throw new Error(String(error)); 43 | } 44 | } 45 | }; 46 | 47 | export const getBaseUrl = (): string | undefined => { 48 | // @ts-expect-error context is available in model apps 49 | return (context as any).page.getClientUrl() as string; 50 | }; 51 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/services/pcfContext.tsx: -------------------------------------------------------------------------------- 1 | 2 | import * as React from "react"; 3 | import { PcfContextService } from './pcfContextService' 4 | // Provides a React context for sharing the PCF context service across the component tree. 5 | 6 | // Props for the PcfContextProvider component 7 | interface PcfContextProviderProps { 8 | pcfcontext: PcfContextService; 9 | children: React.ReactNode; 10 | } 11 | 12 | 13 | // Create a React context for the PCF context service 14 | const PcfContext = React.createContext(undefined!) 15 | 16 | // Provider component for the PCF context service 17 | export const PcfContextProvider = ({ pcfcontext, children }: PcfContextProviderProps) => { 18 | return ( 19 | 20 | {children} 21 | 22 | ) 23 | } 24 | 25 | 26 | // Custom hook to access the PCF context service 27 | export const usePcfContext = () => { 28 | return React.useContext(PcfContext); 29 | } 30 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Scheduler Test 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/test/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import TestApp from "./testApp"; 4 | 5 | createRoot(document.getElementById('root')!).render( 6 | 7 | 8 | , 9 | ) 10 | -------------------------------------------------------------------------------- /Scheduler/Scheduler/test/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "module": "ES2020", 5 | "target": "ESNext", 6 | "lib": [ 7 | "ES2020", 8 | "DOM", 9 | "DOM.Iterable" 10 | ], 11 | "jsx": "react-jsx", 12 | "moduleResolution": "node", // Use "node" for best compatibility 13 | "allowImportingTsExtensions": true, 14 | "verbatimModuleSyntax": true, 15 | "moduleDetection": "force", 16 | "noEmit": true, 17 | "esModuleInterop": true, 18 | "types": [ 19 | "vite/client", 20 | "node" 21 | ] 22 | }, 23 | "include": [ 24 | "./**/*.tsx", 25 | "./**/*.ts" 26 | ], 27 | "exclude": [ 28 | "../../out", 29 | "../../node_modules" 30 | ] 31 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/test/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | 4 | export default defineConfig({ 5 | root: __dirname, 6 | plugins: [react()], 7 | server: { 8 | port: 5173, 9 | open: true 10 | }, 11 | build: { 12 | outDir: "dist" 13 | } 14 | }); -------------------------------------------------------------------------------- /Scheduler/Scheduler/types/extendedSchedulerData.ts: -------------------------------------------------------------------------------- 1 | import { SchedulerData, SchedulerDataConfig, EventItem, SchedulerDataBehaviors } from "react-big-schedule"; 2 | 3 | export interface ExtendedSchedulerDataConfig extends SchedulerDataConfig { 4 | workWeekDays?: number[]; 5 | eventItemPopoverShowColor?: boolean; // <-- add this line 6 | } 7 | 8 | export class ExtendedSchedulerData extends SchedulerData { 9 | config: ExtendedSchedulerDataConfig; 10 | 11 | constructor( 12 | startDate: string, 13 | viewType: number, 14 | showAgenda: boolean, 15 | isEventPerspective: boolean, 16 | config: ExtendedSchedulerDataConfig, 17 | behaviors?: SchedulerDataBehaviors 18 | ) { 19 | super(startDate, viewType, showAgenda, isEventPerspective, config, behaviors); 20 | this.config = config; 21 | } 22 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./schedulerTypes"; 2 | export * from "./schedulerViews"; 3 | export * from "./extendedSchedulerData"; 4 | // Add other type files here as needed -------------------------------------------------------------------------------- /Scheduler/Scheduler/utils/constants.ts: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Default view names for the scheduler, used when no available views are specified. 4 | */ 5 | export const DEFAULT_VIEW_NAMES = ["day", "week", "month", "year", "event"]; 6 | 7 | /** 8 | * Default date format for the scheduler (ISO format) 9 | */ 10 | export const DEFAULT_DATE_FORMAT = "YYYY-MM-DD"; 11 | 12 | /** 13 | * Default time format for the scheduler (24-hour format) 14 | */ 15 | export const DEFAULT_TIME_FORMAT = "HH:mm:ss"; 16 | 17 | /** 18 | * Supported language codes for localization 19 | */ 20 | export const SUPPORTED_LANGUAGES = ["en", "es", "fr", "de", "pt"]; -------------------------------------------------------------------------------- /Scheduler/Scheduler/utils/formattingHelpers.ts: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Formats a Date object as a string suitable for Dynamics form parameters. 4 | * Example output: "5/19/2025 14:30:00" 5 | * @param date - Date object to format 6 | * @returns formatted date string 7 | */ 8 | export function formatDateAsParameterString(date: Date): string { 9 | return ( 10 | date.getMonth() + 1 11 | ) + "/" + 12 | date.getDate() + "/" + 13 | date.getFullYear() + " " + 14 | date.getHours() + ":" + 15 | date.getMinutes() + ":" + 16 | date.getSeconds(); 17 | } 18 | 19 | 20 | /** 21 | * Parses a date string in "YYYY-MM-DD" format and returns a Date object (local time). 22 | * @param dateString - date string in ISO format 23 | * @returns Date object (local time, no time component) 24 | */ 25 | export function parseDateOnly(dateString: string): Date { 26 | // Expects "YYYY-MM-DD" 27 | const [year, month, day] = dateString.split("-").map(Number); 28 | return new Date(year, month - 1, day); // JS months are 0-based 29 | } 30 | 31 | 32 | /** 33 | * Converts a language code like 'en' to 'en_EN', 'es' to 'es_ES', etc. 34 | * If the code is empty or not recognized, defaults to 'en_EN'. 35 | * @param lang - language code (e.g., 'en', 'es') 36 | * @returns locale string (e.g., 'en_EN') 37 | */ 38 | export function getLocaleFromLanguage(lang: string): string { 39 | if (!lang) return "en_EN"; 40 | const code = lang.toLowerCase(); 41 | return `${code}_${code.toUpperCase()}`; 42 | } -------------------------------------------------------------------------------- /Scheduler/Scheduler/utils/locales.ts: -------------------------------------------------------------------------------- 1 | import 'dayjs/locale/en'; 2 | import 'dayjs/locale/es'; 3 | import 'dayjs/locale/fr'; 4 | import 'dayjs/locale/de'; 5 | import 'dayjs/locale/pt'; 6 | import 'antd/locale/en_US'; 7 | import 'antd/locale/es_ES'; 8 | import 'antd/locale/fr_FR'; 9 | import 'antd/locale/de_DE'; 10 | import 'antd/locale/pt_PT'; -------------------------------------------------------------------------------- /Scheduler/Solution/RAWSchedulerComponent/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj 6 | 7 | # MSBuild Binary and Structured Log 8 | *.binlog 9 | -------------------------------------------------------------------------------- /Scheduler/Solution/RAWSchedulerComponent/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /Scheduler/Solution/RAWSchedulerComponent/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /Scheduler/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import eslintjs from "@eslint/js"; 2 | import microsoftPowerApps from "@microsoft/eslint-plugin-power-apps"; 3 | import pluginPromise from "eslint-plugin-promise"; 4 | import globals from "globals"; 5 | import typescriptEslint from "typescript-eslint"; 6 | 7 | /** @type {import('eslint').Linter.Config[]} */ 8 | export default [ 9 | { 10 | ignores: ["**/generated/", "**/mocks/*.ts", "**/out/", "**/*.mjs"], 11 | }, 12 | eslintjs.configs.recommended, 13 | ...typescriptEslint.configs.recommended, 14 | ...typescriptEslint.configs.stylistic, 15 | pluginPromise.configs["flat/recommended"], 16 | microsoftPowerApps.configs.paCheckerHosted, 17 | { 18 | plugins: { 19 | "@microsoft/power-apps": microsoftPowerApps, 20 | }, 21 | 22 | languageOptions: { 23 | globals: { 24 | ...globals.browser, 25 | ComponentFramework: true, 26 | }, 27 | parserOptions: { 28 | ecmaVersion: 2020, 29 | sourceType: "module", 30 | projectService: true, 31 | tsconfigRootDir: import.meta.dirname 32 | }, 33 | }, 34 | 35 | rules: { 36 | "@typescript-eslint/no-unused-vars": "off", 37 | }, 38 | }, 39 | ]; 40 | -------------------------------------------------------------------------------- /Scheduler/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "pcfAllowCustomWebpack": "on" 3 | } -------------------------------------------------------------------------------- /Scheduler/images/scheduler-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/Scheduler/images/scheduler-demo.gif -------------------------------------------------------------------------------- /Scheduler/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes", 14 | "dev:test": "vite --config Scheduler/test/vite.config.ts" 15 | }, 16 | "dependencies": { 17 | "antd": "^5.25.1", 18 | "axios": "^1.9.0", 19 | "color": "^5.0.0", 20 | "dayjs": "^1.11.13", 21 | "lcid": "^5.0.0", 22 | "react": "^18.3.1", 23 | "react-big-schedule": "^4.5.1", 24 | "react-dnd": "^14.0.5", 25 | "react-dnd-html5-backend": "^14.0.5", 26 | "react-dom": "^18.3.1", 27 | "uuid": "^11.1.0" 28 | }, 29 | "devDependencies": { 30 | "@eslint/js": "^9.17.0", 31 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 32 | "@types/node": "^18.19.54", 33 | "@types/powerapps-component-framework": "^1.3.15", 34 | "@types/react-big-scheduler": "^0.2.7", 35 | "@types/react-dom": "^19.1.5", 36 | "@vitejs/plugin-react": "^4.4.1", 37 | "eslint-plugin-promise": "^7.1.0", 38 | "globals": "15.13.0", 39 | "pcf-scripts": "^1", 40 | "pcf-start": "^1", 41 | "typescript": "^5.8.3", 42 | "typescript-eslint": "^8.18.1", 43 | "vite": "^6.3.5" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Scheduler/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /Scheduler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": [ 5 | "node_modules/@types" 6 | ], 7 | "allowSyntheticDefaultImports": true, 8 | "esModuleInterop": true, 9 | "jsx": "react-jsx" 10 | }, 11 | "exclude": ["./out"] 12 | } -------------------------------------------------------------------------------- /WorldDaylightMap/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:promise/recommended" 10 | ], 11 | "globals": { 12 | "ComponentFramework": true 13 | }, 14 | "parser": "@typescript-eslint/parser", 15 | "parserOptions": { 16 | "ecmaVersion": 2020, 17 | "sourceType": "module" 18 | }, 19 | "plugins": [ 20 | "@microsoft/power-apps", 21 | "@typescript-eslint" 22 | ], 23 | "rules": { 24 | "@typescript-eslint/no-unused-vars": "off" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WorldDaylightMap/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # generated directory 7 | **/generated 8 | 9 | # output directory 10 | /out 11 | 12 | # msbuild output directories 13 | /bin 14 | /obj -------------------------------------------------------------------------------- /WorldDaylightMap/Sample/World Daylight Map.msapp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/WorldDaylightMap/Sample/World Daylight Map.msapp -------------------------------------------------------------------------------- /WorldDaylightMap/Solution/RAWWorldDaylightMap/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # msbuild output directories 4 | /bin 5 | /obj -------------------------------------------------------------------------------- /WorldDaylightMap/Solution/RAWWorldDaylightMap/src/Other/Customizations.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1033 17 | 18 | -------------------------------------------------------------------------------- /WorldDaylightMap/Solution/RAWWorldDaylightMap/src/Other/Relationships.xml: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /WorldDaylightMap/WorldDaylightMap/WorldDaylightMap.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {IInputs} from "./generated/ManifestTypes"; 3 | import {WorldDaylightMap} from 'world-daylight-map'; 4 | 5 | export interface IWorldDaylightMapCompProps { 6 | pcfContext: ComponentFramework.Context 7 | } 8 | 9 | export const WorldDaylightMapComp: React.FC = (props) => { 10 | return(
11 | 22 |
); 23 | } 24 | -------------------------------------------------------------------------------- /WorldDaylightMap/WorldDaylightMap/css/WorldDaylightMap.css: -------------------------------------------------------------------------------- 1 | .RAW\.WorldDaylightMap img { 2 | max-width: -webkit-fill-available; 3 | min-width: 0px; 4 | margin-left: auto; 5 | margin-right: auto; 6 | display: block; 7 | } 8 | -------------------------------------------------------------------------------- /WorldDaylightMap/WorldDaylightMap/img/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/WorldDaylightMap/WorldDaylightMap/img/preview.png -------------------------------------------------------------------------------- /WorldDaylightMap/featureconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /WorldDaylightMap/images/world-daylight-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rwilson504/PCFControls/61d3085266806324fc5b48150a7a8a8a237eaffa/WorldDaylightMap/images/world-daylight-map.png -------------------------------------------------------------------------------- /WorldDaylightMap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pcf-project", 3 | "version": "1.0.0", 4 | "description": "Project containing your PowerApps Component Framework (PCF) control.", 5 | "scripts": { 6 | "build": "pcf-scripts build", 7 | "clean": "pcf-scripts clean", 8 | "lint": "pcf-scripts lint", 9 | "lint:fix": "pcf-scripts lint fix", 10 | "rebuild": "pcf-scripts rebuild", 11 | "start": "pcf-scripts start", 12 | "start:watch": "pcf-scripts start watch", 13 | "refreshTypes": "pcf-scripts refreshTypes" 14 | }, 15 | "dependencies": { 16 | "@types/react-dom": "^18.2", 17 | "react": "^18.2", 18 | "react-dom": "^18.2", 19 | "world-daylight-map": "^2" 20 | }, 21 | "devDependencies": { 22 | "@types/node": "^18.19", 23 | "@types/powerapps-component-framework": "^1.3", 24 | "@microsoft/eslint-plugin-power-apps": "^0.2.51", 25 | "@typescript-eslint/eslint-plugin": "^8.18.0", 26 | "@typescript-eslint/parser": "^8.18.0", 27 | "eslint": "^8.57.0", 28 | "eslint-plugin-import": "^2.31.0", 29 | "eslint-plugin-node": "^11.1.0", 30 | "eslint-plugin-promise": "^7.1.0", 31 | "pcf-scripts": "^1", 32 | "pcf-start": "^1", 33 | "typescript": "^4.9.5" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /WorldDaylightMap/pcfconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "outDir": "./out/controls" 3 | } -------------------------------------------------------------------------------- /WorldDaylightMap/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/pcf-scripts/tsconfig_base.json", 3 | "compilerOptions": { 4 | "typeRoots": ["node_modules/@types"], 5 | } 6 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "vite-plugin-dts": "^4.5.4" 4 | } 5 | } 6 | --------------------------------------------------------------------------------