diff --git a/assets/js/components/settings/SettingsActiveModule/Header.js b/assets/js/components/settings/SettingsActiveModule/Header.js index 4a54bc343b9..7500cf8320b 100644 --- a/assets/js/components/settings/SettingsActiveModule/Header.js +++ b/assets/js/components/settings/SettingsActiveModule/Header.js @@ -37,6 +37,7 @@ import { useSelect } from 'googlesitekit-data'; import { Button } from 'googlesitekit-components'; import { CORE_MODULES } from '../../../googlesitekit/modules/datastore/constants'; import { EXPERIMENTAL_MODULES } from '../../dashboard-sharing/DashboardSharingSettings/constants'; +import { NEW_MODULES } from '../constants'; import { Grid, Row, Cell } from '../../../material-components'; import { useKeyCodesInside } from '../../../hooks/useKeyCodesInside'; import ModuleIcon from '../../ModuleIcon'; @@ -180,7 +181,9 @@ export default function Header( { slug } ) { hasLeftSpacing /> ) } - { slug === 'ads' && } + { NEW_MODULES.includes( slug ) && ( + + ) } diff --git a/assets/js/components/settings/SetupModule.js b/assets/js/components/settings/SetupModule.js index fa5f9d4ce57..5849eaaf796 100644 --- a/assets/js/components/settings/SetupModule.js +++ b/assets/js/components/settings/SetupModule.js @@ -42,6 +42,7 @@ import { CORE_SITE } from '../../googlesitekit/datastore/site/constants'; import { CORE_MODULES } from '../../googlesitekit/modules/datastore/constants'; import { CORE_LOCATION } from '../../googlesitekit/datastore/location/constants'; import { EXPERIMENTAL_MODULES } from '../dashboard-sharing/DashboardSharingSettings/constants'; +import { NEW_MODULES } from './constants'; import { trackEvent } from '../../util'; import useViewContext from '../../hooks/useViewContext'; @@ -114,7 +115,9 @@ export default function SetupModule( { slug, name, description } ) { label={ __( 'Experimental', 'google-site-kit' ) } /> ) } - { slug === 'ads' && } + { NEW_MODULES.includes( slug ) && ( + + ) }

diff --git a/assets/js/components/settings/constants.js b/assets/js/components/settings/constants.js new file mode 100644 index 00000000000..60a60c78933 --- /dev/null +++ b/assets/js/components/settings/constants.js @@ -0,0 +1,19 @@ +/** + * Settings constants. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const NEW_MODULES = [ 'ads', 'reader-revenue-manager' ]; diff --git a/assets/js/googlesitekit-modules-reader-revenue-manager.js b/assets/js/googlesitekit-modules-reader-revenue-manager.js new file mode 100644 index 00000000000..beff1a09e08 --- /dev/null +++ b/assets/js/googlesitekit-modules-reader-revenue-manager.js @@ -0,0 +1,30 @@ +/** + * Reader Revenue Manager module entrypoint. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import Data from 'googlesitekit-data'; +import Modules from 'googlesitekit-modules'; +import { + registerStore, + registerModule, +} from './modules/reader-revenue-manager'; + +registerStore( Data ); +registerModule( Modules ); diff --git a/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.js b/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.js new file mode 100644 index 00000000000..19e6cf56ad3 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.js @@ -0,0 +1,37 @@ +/** + * Reader Revenue Manager SettingsEdit component. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +export default function SettingsEdit() { + return ( +

+

+ { __( + 'Reader Revenue Manager Settings Edit', + 'google-site-kit' + ) } +

+ + { /* TODO: Add the rest of the settings steps */ } +
+ ); +} diff --git a/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.stories.js b/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.stories.js new file mode 100644 index 00000000000..9901e1830c6 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.stories.js @@ -0,0 +1,34 @@ +/** + * Reader Revenue Manager SettingsEdit component stories. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import SettingsEdit from './SettingsEdit'; + +function Template() { + return ; +} + +export const Default = Template.bind( {} ); +Default.storyName = 'Default'; + +export default { + title: 'Modules/ReaderRevenueManager/Settings/SettingsEdit', + component: SettingsEdit, +}; diff --git a/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.test.js b/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.test.js new file mode 100644 index 00000000000..66bf0edc12c --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/settings/SettingsEdit.test.js @@ -0,0 +1,30 @@ +/** + * Reader Revenue Manager SettingsEdit component tests. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { render } from '../../../../../../tests/js/test-utils'; +import SettingsEdit from './SettingsEdit'; + +describe( 'SettingsEdit', () => { + it( 'should render the component', () => { + const { getByText } = render( ); + + expect( + getByText( /Reader Revenue Manager Settings Edit/i ) + ).toBeInTheDocument(); + } ); +} ); diff --git a/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.js b/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.js new file mode 100644 index 00000000000..dfe95f39571 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.js @@ -0,0 +1,37 @@ +/** + * Reader Revenue Manager SettingsView component. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +export default function SettingsView() { + return ( +
+

+ { __( + 'Reader Revenue Manager Settings View', + 'google-site-kit' + ) } +

+ + { /* TODO: Add the rest of the settings steps */ } +
+ ); +} diff --git a/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.stories.js b/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.stories.js new file mode 100644 index 00000000000..3f317700f12 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.stories.js @@ -0,0 +1,34 @@ +/** + * Reader Revenue Manager SettingsView component stories. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import SettingsView from './SettingsView'; + +function Template() { + return ; +} + +export const Default = Template.bind( {} ); +Default.storyName = 'Default'; + +export default { + title: 'Modules/ReaderRevenueManager/Settings/SettingsView', + component: SettingsView, +}; diff --git a/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.test.js b/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.test.js new file mode 100644 index 00000000000..96e585ac452 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/settings/SettingsView.test.js @@ -0,0 +1,30 @@ +/** + * Reader Revenue Manager SettingsView component tests. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { render } from '../../../../../../tests/js/test-utils'; +import SettingsView from './SettingsView'; + +describe( 'SettingsView', () => { + it( 'should render the component', () => { + const { getByText } = render( ); + + expect( + getByText( /Reader Revenue Manager Settings View/i ) + ).toBeInTheDocument(); + } ); +} ); diff --git a/assets/js/modules/reader-revenue-manager/components/settings/index.js b/assets/js/modules/reader-revenue-manager/components/settings/index.js new file mode 100644 index 00000000000..a5495ca2804 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/settings/index.js @@ -0,0 +1,20 @@ +/** + * Reader Revenue Manager Settings components. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { default as SettingsEdit } from './SettingsEdit'; +export { default as SettingsView } from './SettingsView'; diff --git a/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.js b/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.js new file mode 100644 index 00000000000..97fc654097e --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.js @@ -0,0 +1,47 @@ +/** + * Reader Revenue Manager SetupMain component. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * WordPress dependencies + */ +import { _x } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import ReaderRevenueManagerIcon from '../../../../../svg/graphics/reader-revenue-manager.svg'; + +export default function SetupMain() { + return ( +
+
+ +
+ +

+ { _x( + 'Reader Revenue Manager', + 'Service name', + 'google-site-kit' + ) } +

+ + { /* TODO: Add the rest of the setup steps */ } +
+ ); +} diff --git a/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.stories.js b/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.stories.js new file mode 100644 index 00000000000..f83618bbdc4 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.stories.js @@ -0,0 +1,34 @@ +/** + * Reader Revenue Manager SetupMain component stories. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import SetupMain from './SetupMain'; + +function Template() { + return ; +} + +export const Default = Template.bind( {} ); +Default.storyName = 'Default'; + +export default { + title: 'Modules/ReaderRevenueManager/Setup/SetupMain', + component: SetupMain, +}; diff --git a/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.test.js b/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.test.js new file mode 100644 index 00000000000..62b8d736342 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/setup/SetupMain.test.js @@ -0,0 +1,28 @@ +/** + * Reader Revenue Manager SetupMain component tests. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { render } from '../../../../../../tests/js/test-utils'; +import SetupMain from './SetupMain'; + +describe( 'SetupMain', () => { + it( 'should render the component', () => { + const { getByText } = render( ); + + expect( getByText( /Reader Revenue Manager/i ) ).toBeInTheDocument(); + } ); +} ); diff --git a/assets/js/modules/reader-revenue-manager/components/setup/index.js b/assets/js/modules/reader-revenue-manager/components/setup/index.js new file mode 100644 index 00000000000..d0c584f8d23 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/components/setup/index.js @@ -0,0 +1,19 @@ +/** + * Reader Revenue Manager Setup components. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { default as SetupMain } from './SetupMain'; diff --git a/assets/js/modules/reader-revenue-manager/datastore/base.js b/assets/js/modules/reader-revenue-manager/datastore/base.js new file mode 100644 index 00000000000..da7cfb7a972 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/datastore/base.js @@ -0,0 +1,29 @@ +/** + * `modules/reader-revenue-manager` base data store. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import Modules from 'googlesitekit-modules'; +import { MODULES_READER_REVENUE_MANAGER } from './constants'; +import { validateCanSubmitChanges } from './settings'; + +export default Modules.createModuleStore( 'reader-revenue-manager', { + storeName: MODULES_READER_REVENUE_MANAGER, + validateCanSubmitChanges, +} ); diff --git a/assets/js/modules/reader-revenue-manager/datastore/base.test.js b/assets/js/modules/reader-revenue-manager/datastore/base.test.js new file mode 100644 index 00000000000..98413b2567e --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/datastore/base.test.js @@ -0,0 +1,51 @@ +/** + * `modules/reader-revenue-manager` base data store tests. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import { + createTestRegistry, + provideSiteInfo, +} from '../../../../../tests/js/utils'; +import { MODULES_READER_REVENUE_MANAGER } from './constants'; + +describe( 'modules/reader-revenue-manager base data store', () => { + let registry; + let store; + + beforeEach( () => { + jest.resetModules(); + + registry = createTestRegistry(); + provideSiteInfo( registry ); + } ); + + it( 'does not define the admin page', () => { + store = require( './base' ).default; + registry.registerStore( MODULES_READER_REVENUE_MANAGER, store ); + + expect( + registry + .select( MODULES_READER_REVENUE_MANAGER ) + .getAdminScreenURL() + ).toBe( + 'http://example.com/wp-admin/admin.php?page=googlesitekit-dashboard' + ); + } ); +} ); diff --git a/assets/js/modules/reader-revenue-manager/datastore/constants.js b/assets/js/modules/reader-revenue-manager/datastore/constants.js new file mode 100644 index 00000000000..bd47a04d973 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/datastore/constants.js @@ -0,0 +1,21 @@ +/** + * `modules/reader-revenue-manager` data store constants. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const MODULES_READER_REVENUE_MANAGER = 'modules/reader-revenue-manager'; + +export const ERROR_CODE_NON_HTTPS_SITE = 'non_https_site'; diff --git a/assets/js/modules/reader-revenue-manager/datastore/index.js b/assets/js/modules/reader-revenue-manager/datastore/index.js new file mode 100644 index 00000000000..9ce3ea73875 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/datastore/index.js @@ -0,0 +1,39 @@ +/** + * `modules/reader-revenue-manager` data store. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import { combineStores } from 'googlesitekit-data'; +import { MODULES_READER_REVENUE_MANAGER } from './constants'; +import baseModuleStore from './base'; + +const store = combineStores( baseModuleStore ); + +export const initialState = store.initialState; +export const actions = store.actions; +export const controls = store.controls; +export const reducer = store.reducer; +export const resolvers = store.resolvers; +export const selectors = store.selectors; + +export const registerStore = ( registry ) => { + registry.registerStore( MODULES_READER_REVENUE_MANAGER, store ); +}; + +export default store; diff --git a/assets/js/modules/reader-revenue-manager/datastore/index.test.js b/assets/js/modules/reader-revenue-manager/datastore/index.test.js new file mode 100644 index 00000000000..1d7dfd0f5f9 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/datastore/index.test.js @@ -0,0 +1,43 @@ +/** + * `modules/reader-revenue-manager` data store: selectors test. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import { + createTestRegistry, + unsubscribeFromAll, +} from '../../../../../tests/js/utils'; + +describe( 'modules/reader-revenue-manager properties', () => { + let registry; + + beforeEach( () => { + registry = createTestRegistry(); + } ); + + afterEach( () => { + unsubscribeFromAll( registry ); + } ); + + describe( 'store', () => { + it( 'is registered correctly', () => { + // TODO: Implement tests as part of #8793. + } ); + } ); +} ); diff --git a/assets/js/modules/reader-revenue-manager/datastore/settings.js b/assets/js/modules/reader-revenue-manager/datastore/settings.js new file mode 100644 index 00000000000..57c408bef23 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/datastore/settings.js @@ -0,0 +1,55 @@ +/** + * `modules/reader-revenue-manager` data store: settings actions. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import invariant from 'invariant'; + +/** + * Internal dependencies + */ +import { MODULES_READER_REVENUE_MANAGER } from './constants'; +import { + INVARIANT_DOING_SUBMIT_CHANGES, + INVARIANT_SETTINGS_NOT_CHANGED, +} from '../../../googlesitekit/data/create-settings-store'; +import { createStrictSelect } from '../../../googlesitekit/data/utils'; +import { isValidPublicationID } from '../utils/validation'; + +// Invariant error messages. +export const INVARIANT_INVALID_PUBLICATION_ID = + 'a valid publicationID is required'; + +export function validateCanSubmitChanges( select ) { + const strictSelect = createStrictSelect( select ); + // Strict select will cause all selector functions to throw an error + // if `undefined` is returned, otherwise it behaves the same as `select`. + // This ensures that the selector returns `false` until all data dependencies are resolved. + const { haveSettingsChanged, isDoingSubmitChanges, getPublicationID } = + strictSelect( MODULES_READER_REVENUE_MANAGER ); + + invariant( ! isDoingSubmitChanges(), INVARIANT_DOING_SUBMIT_CHANGES ); + invariant( haveSettingsChanged(), INVARIANT_SETTINGS_NOT_CHANGED ); + + const publicationID = getPublicationID(); + invariant( + isValidPublicationID( publicationID ), + INVARIANT_INVALID_PUBLICATION_ID + ); +} diff --git a/assets/js/modules/reader-revenue-manager/datastore/settings.test.js b/assets/js/modules/reader-revenue-manager/datastore/settings.test.js new file mode 100644 index 00000000000..f772e88a2bb --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/datastore/settings.test.js @@ -0,0 +1,52 @@ +/** + * `modules/reader-revenue-manager` data store: settings tests. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import API from 'googlesitekit-api'; +import { + createTestRegistry, + unsubscribeFromAll, +} from '../../../../../tests/js/utils'; + +describe( 'modules/reader-revenue-manager settings', () => { + let registry; + + beforeAll( () => { + API.setUsingCache( false ); + } ); + + beforeEach( () => { + registry = createTestRegistry(); + } ); + + afterEach( () => { + unsubscribeFromAll( registry ); + } ); + + afterAll( () => { + API.setUsingCache( true ); + } ); + + describe( 'validateCanSubmitChanges', () => { + it( 'it validates', () => { + // TODO: Implement tests as part of #8793. + } ); + } ); +} ); diff --git a/assets/js/modules/reader-revenue-manager/index.js b/assets/js/modules/reader-revenue-manager/index.js new file mode 100644 index 00000000000..8f95b53edac --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/index.js @@ -0,0 +1,79 @@ +/** + * Reader Revenue Manager module initialization. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { CORE_SITE } from '../../googlesitekit/datastore/site/constants'; +import { + MODULES_READER_REVENUE_MANAGER, + ERROR_CODE_NON_HTTPS_SITE, +} from './datastore/constants'; +import { SetupMain } from './components/setup'; +import { SettingsEdit, SettingsView } from './components/settings'; +import ReaderRevenueManagerIcon from '../../../svg/graphics/reader-revenue-manager.svg'; +import { isFeatureEnabled } from '../../features'; +import { isURLUsingHTTPS } from './utils/validation'; + +export { registerStore } from './datastore'; + +const isRrmModuleEnabled = + ( func ) => + ( ...args ) => { + if ( isFeatureEnabled( 'rrmModule' ) ) { + func( ...args ); + } + }; + +export const registerModule = isRrmModuleEnabled( ( modules ) => { + modules.registerModule( 'reader-revenue-manager', { + storeName: MODULES_READER_REVENUE_MANAGER, + SettingsEditComponent: SettingsEdit, + SettingsViewComponent: SettingsView, + SetupComponent: SetupMain, + Icon: ReaderRevenueManagerIcon, + features: [ + // TODO: Implement the features as part of #8845. + ], + checkRequirements: async ( registry ) => { + // Ensure the site info is resolved to get the home URL. + await registry + .__experimentalResolveSelect( CORE_SITE ) + .getSiteInfo(); + const homeURL = registry.select( CORE_SITE ).getHomeURL(); + + if ( isURLUsingHTTPS( homeURL ) ) { + return; + } + + throw { + code: ERROR_CODE_NON_HTTPS_SITE, + message: __( + 'The site should use HTTPS to set up Reader Revenue Manager', + 'google-site-kit' + ), + data: null, + }; + }, + } ); +} ); diff --git a/assets/js/modules/reader-revenue-manager/utils/validation.js b/assets/js/modules/reader-revenue-manager/utils/validation.js new file mode 100644 index 00000000000..507a2693c06 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/utils/validation.js @@ -0,0 +1,54 @@ +/** + * Validation utilities. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Checks if the given publication ID appears to be a valid. + * + * @since n.e.x.t + * + * @param {string} publicationID Publication ID to test. + * @return {boolean} `true` if the given publication ID is valid, `false` otherwise. + */ +export function isValidPublicationID( publicationID ) { + return ( + typeof publicationID === 'string' && + /^[A-Za-z0-9_-]+$/.test( publicationID ) + ); +} + +/** + * Checks if a given URL uses HTTPS. + * + * @since n.e.x.t + * + * @param {string} url The URL to check. + * @return {boolean} True if the URL uses HTTPS, false otherwise. + */ +export const isURLUsingHTTPS = ( url ) => { + try { + if ( typeof url !== 'string' || ! url ) { + throw new TypeError( `Invalid URL: ${ url }` ); + } + + const parsedURL = new URL( url ); + return parsedURL.protocol === 'https:'; + } catch ( error ) { + global.console.warn( 'Invalid URL:', error ); + return false; + } +}; diff --git a/assets/js/modules/reader-revenue-manager/utils/validation.test.js b/assets/js/modules/reader-revenue-manager/utils/validation.test.js new file mode 100644 index 00000000000..b2000b896a8 --- /dev/null +++ b/assets/js/modules/reader-revenue-manager/utils/validation.test.js @@ -0,0 +1,69 @@ +/** + * Validation function tests. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Internal dependencies + */ +import { isValidPublicationID, isURLUsingHTTPS } from './validation'; + +describe( 'utility functions', () => { + describe( 'isValidPublicationID', () => { + it( 'should return TRUE when a valid publication ID is passed', () => { + expect( isValidPublicationID( 'valid_publication-123' ) ).toBe( + true + ); + } ); + + it.each( [ + [ 'false', false ], + [ 'an integer', 12345 ], + [ 'an empty string', '' ], + [ 'a string with invalid characters', 'invalid.publication!ID' ], + [ 'a string with periods', 'invalid.publication.ID' ], + ] )( 'should return FALSE when %s is passed', ( _, publicationID ) => { + expect( isValidPublicationID( publicationID ) ).toBe( false ); + } ); + } ); + + describe( 'isURLUsingHTTPS', () => { + it( 'should return TRUE when a URL with HTTPS is passed', () => { + expect( isURLUsingHTTPS( 'https://example.com' ) ).toBe( true ); + expect( console ).not.toHaveWarned(); + } ); + + it.each( [ + [ 'a string without protocol', 'example.com' ], + [ 'an empty string', '' ], + [ 'false', false ], + ] )( 'should return FALSE and warn when %s is passed', ( _, url ) => { + expect( isURLUsingHTTPS( url ) ).toBe( false ); + expect( console ).toHaveWarned(); + } ); + + it.each( [ + [ 'an HTTP URL', 'http://example.com' ], + [ 'an invalid URL', 'htp://example.com' ], + ] )( + 'should return FALSE but not warn when %s is passed', + ( _, url ) => { + expect( isURLUsingHTTPS( url ) ).toBe( false ); + expect( console ).not.toHaveWarned(); + } + ); + } ); +} ); diff --git a/assets/svg/graphics/reader-revenue-manager.svg b/assets/svg/graphics/reader-revenue-manager.svg new file mode 100644 index 00000000000..8860e5d866d --- /dev/null +++ b/assets/svg/graphics/reader-revenue-manager.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/includes/Modules/Reader_Revenue_Manager.php b/includes/Modules/Reader_Revenue_Manager.php index bd49d782cef..c19d98202f5 100644 --- a/includes/Modules/Reader_Revenue_Manager.php +++ b/includes/Modules/Reader_Revenue_Manager.php @@ -10,7 +10,10 @@ namespace Google\Site_Kit\Modules; +use Google\Site_Kit\Core\Assets\Script; use Google\Site_Kit\Core\Modules\Module; +use Google\Site_Kit\Core\Modules\Module_With_Assets; +use Google\Site_Kit\Core\Modules\Module_With_Assets_Trait; use Google\Site_Kit\Core\Modules\Module_With_Scopes; use Google\Site_Kit\Core\Modules\Module_With_Scopes_Trait; @@ -21,7 +24,8 @@ * @access private * @ignore */ -final class Reader_Revenue_Manager extends Module implements Module_With_Scopes { +final class Reader_Revenue_Manager extends Module implements Module_With_Scopes, Module_With_Assets { + use Module_With_Assets_Trait; use Module_With_Scopes_Trait; /** @@ -67,4 +71,33 @@ protected function setup_info() { 'homepage' => __( 'https://readerrevenue.withgoogle.com/', 'google-site-kit' ), ); } + + /** + * Sets up the module's assets to register. + * + * @since n.e.x.t + * + * @return Asset[] List of Asset objects. + */ + protected function setup_assets() { + $base_url = $this->context->url( 'dist/assets/' ); + + return array( + new Script( + 'googlesitekit-modules-reader-revenue-manager', + array( + 'src' => $base_url . 'js/googlesitekit-modules-reader-revenue-manager.js', + 'dependencies' => array( + 'googlesitekit-vendor', + 'googlesitekit-api', + 'googlesitekit-data', + 'googlesitekit-modules', + 'googlesitekit-datastore-site', + 'googlesitekit-datastore-user', + 'googlesitekit-components', + ), + ) + ), + ); + } } diff --git a/tests/js/utils.js b/tests/js/utils.js index ad379800e2b..45c9f13343c 100644 --- a/tests/js/utils.js +++ b/tests/js/utils.js @@ -42,6 +42,7 @@ import * as modulesAds from '../../assets/js/modules/ads'; import * as modulesAdSense from '../../assets/js/modules/adsense'; import * as modulesAnalytics4 from '../../assets/js/modules/analytics-4'; import * as modulesPageSpeedInsights from '../../assets/js/modules/pagespeed-insights'; +import * as modulesReaderRevenueManager from '../../assets/js/modules/reader-revenue-manager'; import * as modulesSearchConsole from '../../assets/js/modules/search-console'; import * as modulesTagManager from '../../assets/js/modules/tagmanager'; import { CORE_SITE } from '../../assets/js/googlesitekit/datastore/site/constants'; @@ -74,6 +75,7 @@ const allCoreModules = [ modulesAdSense, modulesAnalytics4, modulesPageSpeedInsights, + modulesReaderRevenueManager, modulesSearchConsole, modulesTagManager, ]; diff --git a/webpack/modules.config.js b/webpack/modules.config.js index d8301f79f48..31d115159e3 100644 --- a/webpack/modules.config.js +++ b/webpack/modules.config.js @@ -74,6 +74,8 @@ module.exports = ( mode, rules, ANALYZE ) => { './assets/js/googlesitekit-modules-analytics-4.js', 'googlesitekit-modules-pagespeed-insights': 'assets/js/googlesitekit-modules-pagespeed-insights.js', + 'googlesitekit-modules-reader-revenue-manager': + './assets/js/googlesitekit-modules-reader-revenue-manager.js', 'googlesitekit-modules-search-console': './assets/js/googlesitekit-modules-search-console.js', 'googlesitekit-modules-tagmanager':